From 80eeca0127d4a17c721bc077a04c96db5823a3b9 Mon Sep 17 00:00:00 2001 From: bluetegu Date: Thu, 7 Feb 2019 10:44:43 -0500 Subject: [PATCH 1/3] routing: add support for pegged hops in findPaths. Add the ability to query for routes that pass through one or more pre-specified (pegged) hops.The resulting route is composed of segments connecting between the pegged nodes. Each segment does not have loops, but the entire path may. The route selection assures that no edge will be transversed twice at the same direction. The alternate routes are stitched from N-1 shortest segment paths and one alternate segment path. --- routing/errors.go | 5 + routing/pathfind.go | 510 ++++++++++++++++++++++++--- routing/pathfind_test.go | 104 +++++- routing/router.go | 59 +++- routing/router_test.go | 453 +++++++++++++++++++++++- routing/testdata/excessive_hops.json | 96 ++--- rpcserver.go | 4 +- 7 files changed, 1100 insertions(+), 131 deletions(-) diff --git a/routing/errors.go b/routing/errors.go index 0eb6cb37b8..ac4f2bc781 100644 --- a/routing/errors.go +++ b/routing/errors.go @@ -30,6 +30,11 @@ const ( // the channel graph. ErrTargetNotInNetwork + // ErrPegNotInNetwork is returned when one or more of the pegged nodes + // or channels requested from path-finding isn't known to be within + // the current version of the channel graph. + ErrPegNotInNetwork + // ErrOutdated is returned when the routing update already have // been applied, or a newer update is already known. ErrOutdated diff --git a/routing/pathfind.go b/routing/pathfind.go index 65db06cb75..f899afe35e 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -38,6 +38,11 @@ const ( // some effect with smaller time lock values. The value may need // tweaking and/or be made configurable in the future. RiskFactorBillionths = 15 + + // noFeeLimit is the maximum value of a payment through Lightning. We + // can use this value to signal there is no fee limit since payments + // should never be larger than this. + noFeeLimit = lnwire.MilliSatoshi(math.MaxUint32) ) // HopHint is a routing hint that contains the minimum information of a channel @@ -62,6 +67,17 @@ type HopHint struct { CLTVExpiryDelta uint16 } +// HopPeg is a routing peg that the route must pass through. It includes a +// Node ID and an optional Channel ID that leads to it. +type HopPeg struct { + // NodeID is the public key of the node at the start of the channel. + NodeID *btcec.PublicKey + + // ChannelID is the unique identifier of the channel, or 0 if no + // specific is pegged. + ChannelID uint64 +} + // Hop represents an intermediate or final node of the route. This naming // is in line with the definition given in BOLT #4: Onion Routing Protocol. // The struct houses the channel along which this hop can be reached and @@ -104,6 +120,45 @@ func computeFee(amt lnwire.MilliSatoshi, return edge.FeeBaseMSat + (amt*edge.FeeProportionalMillionths)/1000000 } +func computePathFee(amt lnwire.MilliSatoshi, + pathEdges []*channeldb.ChannelEdgePolicy) lnwire.MilliSatoshi { + + var nextIncomingAmount lnwire.MilliSatoshi + pathLength := len(pathEdges) + for i := pathLength - 1; i >= 0; i-- { + + // If this is the last hop, then the hop payload will contain + // the exact amount. In BOLT #4: Onion Routing + // Protocol / "Payload for the Last Node", this is detailed. + amtToForward := amt + + // Fee is not part of the hop payload, but only used for + // reporting through RPC. Set to zero for the final hop. + fee := lnwire.MilliSatoshi(0) + + // If the current hop isn't the last hop, then add enough funds + // to pay for transit over the next link. + if i != len(pathEdges)-1 { + // The amount that the current hop needs to forward is + // equal to the incoming amount of the next hop. + amtToForward = nextIncomingAmount + + // The fee that needs to be paid to the current hop is + // based on the amount that this hop needs to forward + // and its policy for the outgoing channel. This policy + // is stored as part of the incoming channel of + // the next hop. + fee = computeFee(amtToForward, pathEdges[i+1]) + } + + // Finally, we update the amount that needs to flow into the + // *next* hop, which is the amount this hop needs to forward, + // accounting for the fee that it takes. + nextIncomingAmount = amtToForward + fee + } + return nextIncomingAmount - amt +} + // isSamePath returns true if path1 and path2 travel through the exact same // edges, and false otherwise. func isSamePath(path1, path2 []*channeldb.ChannelEdgePolicy) bool { @@ -437,6 +492,14 @@ type graphParams struct { // set to the current available sending bandwidth for active local // channels, and 0 for inactive channels. bandwidthHints map[uint64]lnwire.MilliSatoshi + + // originVertex, if not null, points to the origin of the path. The + // distinction between the source and the origin is required when + // calculating spur paths and when stitching together paths to + // pass through peg nodes. It is used to infer whether disabled + // channels should be included in the path, for fee calcuation of + // stitched paths, etc. + originVertex *Vertex } // restrictParams wraps the set of restrictions passed to findPath that the @@ -457,6 +520,12 @@ type restrictParams struct { // outgoingChannelID is the channel that needs to be taken to the first // hop. If nil, any channel may be used. outgoingChannelID *uint64 + + // stopAtMaxHopsExceeded instructs the find path algorithm to + // stop further search attempts if the number of hops of the shortest + // path found is above the maximum. It's main purpose is to prevent + // the search algorithm from entering an infinite recurrsion loop. + stopAtMaxHopsExceeded bool } // findPath attempts to find a path from the source node within the @@ -533,6 +602,10 @@ func findPath(g *graphParams, r *restrictParams, } sourceVertex := Vertex(sourceNode.PubKeyBytes) + originVertex := sourceVertex + if g.originVertex != nil { + originVertex = *g.originVertex + } // We can't always assume that the end destination is publicly // advertised to the network and included in the graph.ForEachNode call @@ -543,7 +616,6 @@ func findPath(g *graphParams, r *restrictParams, targetVertex := NewVertex(target) targetNode := &channeldb.LightningNode{PubKeyBytes: targetVertex} distance[targetVertex] = nodeWithDist{ - dist: 0, node: targetNode, amountToReceive: amt, fee: 0, @@ -566,8 +638,7 @@ func findPath(g *graphParams, r *restrictParams, // skip it. // TODO(halseth): also ignore disable flags for non-local // channels if bandwidth hint is set? - isSourceChan := fromVertex == sourceVertex - + isSourceChan := fromVertex == originVertex edgeFlags := edge.ChannelFlags isDisabled := edgeFlags&lnwire.ChanUpdateDisabled != 0 @@ -622,7 +693,7 @@ func findPath(g *graphParams, r *restrictParams, // node, no additional timelock is required. var fee lnwire.MilliSatoshi var timeLockDelta uint16 - if fromVertex != sourceVertex { + if fromVertex != originVertex { fee = computeFee(amountToSend, edge) timeLockDelta = edge.TimeLockDelta } @@ -795,14 +866,346 @@ func findPath(g *graphParams, r *restrictParams, // hops, then it's invalid. numEdges := len(pathEdges) if numEdges > HopLimit { - return nil, newErr(ErrMaxHopsExceeded, "potential path has "+ - "too many hops") + if r.stopAtMaxHopsExceeded { + return pathEdges, newErr(ErrMaxHopsExceeded, + "potential path has too many hops") + + } + // Make another attempt to find a route which is not the + // shortest path in terms of fees, but with number of + // hops below the max. + pathKEdges, err := findKPaths( + g, + r, + sourceNode, target, + amt, + pathEdges, + 1, + ) + if err != nil || len(pathKEdges) == 0 { + return nil, newErr(ErrMaxHopsExceeded, "shortest"+ + " path has too many hops. No alternate "+ + " path found.") + } + // Remove the first artificial node added at path + // beginning. + pathEdges = pathKEdges[0][1:] } return pathEdges, nil } +// prepareHopPegs adds pegged hops for pegged channel ids. +func prepareHopPegs(graph *channeldb.ChannelGraph, + in []HopPeg) ([]HopPeg, error) { + + var ( + expanded []HopPeg + out []HopPeg + ) + + // If channel id is pegged too, find the node connected to it and + // add it as pegged node. + for i, peg := range in { + if peg.ChannelID != 0 { + if i == 0 { + return nil, newErrf(ErrPegNotInNetwork, + fmt.Sprintf("Error processing "+ + " pegged hops")) + } + edgeInfo, _, _, err := + graph.FetchChannelEdgesByID(peg.ChannelID) + if err != nil { + return nil, err + } + pegVertex := NewVertex(peg.NodeID) + prevHopBytes, err := + edgeInfo.OtherNodeKeyBytes(pegVertex[:]) + if err != nil { + return nil, err + } + pub, err := + btcec.ParsePubKey(prevHopBytes, btcec.S256()) + if err != nil { + return nil, err + } + pPeg := HopPeg{ + NodeID: pub, + } + expanded = append(expanded, pPeg) + } + expanded = append(expanded, peg) + } + + // This should never happen, as both source and target should be + // included in pegged hops. + if len(expanded) < 2 { + return expanded, nil + } + + // Remove duplicate pegs. If a previous hop was added as peg due to + // pegged channel ID, an already existing pegged hop may exist and + // should be removed. + for i, peg := range expanded { + if peg.ChannelID == 0 && i > 0 && + NewVertex(peg.NodeID) == + NewVertex(expanded[i-1].NodeID) { + continue + } + out = append(out, peg) + } + return out, nil +} + // findPaths implements a k-shortest paths algorithm to find all the reachable +// paths between the passed source and target. First the shortest path is found +// and the k-shortest paths are then calculated based on it. +func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph, + source *channeldb.LightningNode, target *btcec.PublicKey, + amt lnwire.MilliSatoshi, feeLimit lnwire.MilliSatoshi, numPaths uint32, + bandwidthHints map[uint64]lnwire.MilliSatoshi, + additionalPegs []HopPeg) ([][]*channeldb.ChannelEdgePolicy, error) { + + ignoredVertexes := make(map[Vertex]struct{}) + ignoredEdges := make(map[edgeLocator]struct{}) + + // TODO(roasbeef): modifying ordering within heap to eliminate final + // sorting step? + var ( + shortestPaths [][]*channeldb.ChannelEdgePolicy + candidatePaths pathHeap + startingPath []*channeldb.ChannelEdgePolicy + pegs []HopPeg + segPaths [][]*channeldb.ChannelEdgePolicy + ) + heap.Init(&candidatePaths) + + // The path is computed in segments, from source to first peg, to + // second peg, etc. until target. The different segments are then + // stitched together to form an end to end shortest path. + src, _ := source.PubKey() + originVertex := NewVertex(src) + + // Include the source and destination as additional pegs. + pegs = append(pegs, HopPeg{NodeID: src}) + pegs = append(pegs, additionalPegs...) + pegs = append(pegs, HopPeg{NodeID: target}) + + // If channel id is pegged too, find the node connected to it and + // add it as pegged node. + pegs, err := prepareHopPegs(graph, pegs) + if err != nil { + return nil, err + } + + // Segment parameters used later to save re-calculations. + type segmentParams struct { + src *channeldb.LightningNode + dest *btcec.PublicKey + pegged bool + } + segParams := make([]*segmentParams, len(pegs)-1) + // Break path to segments between pegs. + for j := 1; j < len(pegs); j++ { + var segPath []*channeldb.ChannelEdgePolicy + peg := pegs[j] + prevPeg := pegs[j-1] + prevNode, err := graph.FetchLightningNode(prevPeg.NodeID) + if err != nil { + return nil, err + } + + // First we'll find a single shortest path from the source + // (prev step) to the target (next step) that's capable of + // carrying amt satoshis along the path before fees are + // calculated. + if peg.ChannelID == 0 { + segPath, err = findPath( + &graphParams{ + tx: tx, + graph: graph, + bandwidthHints: bandwidthHints, + originVertex: &originVertex, + }, + &restrictParams{ + ignoredNodes: ignoredVertexes, + ignoredEdges: ignoredEdges, + feeLimit: feeLimit, + }, + prevNode, peg.NodeID, amt, + ) + if err != nil { + log.Errorf("Unable to find path: %v", err) + return nil, err + } + } else { + // create a one-hop pegged path from previous + // hop through pegged channel. + info, p1, p2, err := + graph.FetchChannelEdgesByID(peg.ChannelID) + if err != nil { + return nil, err + } + + // Select the relevant edge policy. + policy := p2 + nodeID := NewVertex(peg.NodeID) + if bytes.Equal(nodeID[:], info.NodeKey2Bytes[:]) { + policy = p1 + } + segPath = append(segPath, policy) + } + + // Make sure the segment edges are not transversed + // again in next segments of the path + for _, edge := range segPath { + locator := newEdgeLocator(edge) + ignoredEdges[*locator] = struct{}{} + } + + // Stitch the path to the previous steps + startingPath = append(startingPath, segPath...) + + // Keep the shortest segment paths for later stitching + // with alternate paths of other segments. + segPaths = append(segPaths, segPath) + + // Keep segement parameters and save some cycles when + // expanding to K-paths. + segParams[j-1] = &segmentParams{ + src: prevNode, + dest: peg.NodeID, + pegged: peg.ChannelID != 0, + } + } + + // Check thta total fee of stitched path is below the limit. + startingPathFee := computePathFee(amt, startingPath) + if startingPathFee > feeLimit { + log.Errorf("Shortest path exceeds path limit") + return nil, newErr(ErrNoRouteFound, "shortest path exceeds "+ + "fee limit") + } + + // Closure helper for stiching segment path to all other shortest + // segments to form and end to end path. + stitchPath := func(i int, path []*channeldb.ChannelEdgePolicy, + ) (stitched []*channeldb.ChannelEdgePolicy) { + + for j := 0; j < len(segPaths); j++ { + seg := segPaths[j] + if i == j { + seg = path + } + stitched = append(stitched, seg...) + } + return stitched + } + + // For each segment in the path, get up to additional numPath-1 paths. + // Stitch each candidate of segment-i with the shortest path composed + // of all other segments to form a candidate end-to-end path. Then + // select up to numPath end to end shortest paths. This does not + // necessarily end up with the shortest set of paths, rather is a + // complexity compromise. + for i := 0; i < len(segPaths); i++ { + // no point in calculating alternate paths if + // channel is fixed between source and destination. + if segParams[i].pegged { + continue + } + sSrc := segParams[i].src + sDest := segParams[i].dest + sFeeLimit := noFeeLimit + if feeLimit != noFeeLimit { + segFee := computePathFee(amt, segPaths[i]) + sFeeLimit = feeLimit - startingPathFee + segFee + } + // Copy ignored edges apart from edges included in this + // segment. + sIgnoredEdges := make(map[edgeLocator]struct{}) + for k, v := range ignoredEdges { + sIgnoredEdges[k] = v + } + for _, e := range segPaths[i] { + delete(sIgnoredEdges, *newEdgeLocator(e)) + } + + // Get additional paths for the segment. + segKPaths, err := findKPaths( + &graphParams{ + tx: tx, + graph: graph, + bandwidthHints: bandwidthHints, + originVertex: &originVertex, + }, + &restrictParams{ + ignoredNodes: ignoredVertexes, + ignoredEdges: sIgnoredEdges, + feeLimit: sFeeLimit, + }, + sSrc, sDest, + amt, + segPaths[i], + numPaths, + ) + if err != nil { + return nil, err + } + + // Stitch the segment paths found for this segment with the + // shortest paths of all other segments. + for j, segKPath := range segKPaths { + + // Avoid duplicates. The shortest path is selected + // already in the first iteration. + if i != 0 && j == 0 { + continue + } + + // replace the first segment shortest path + // with a replica of itself starting with an + // artificial path from the source node. + if i == 0 && j == 0 { + segPaths[0] = segKPath + } + + // Stitch the segments to an end to end path + stitchedPath := stitchPath(i, segKPath) + stitchedPathLen := len(stitchedPath) + + // Filter out those which are too long. Fee limit + // was already taken into account when calculating + // K paths for the segment. + if stitchedPathLen > HopLimit { + continue + } + + // Push stitched path to list of candidates. + newPath := path{ + hops: stitchedPath, + dist: stitchedPathLen, + } + heap.Push(&candidatePaths, newPath) + } + } + + // Select best candidates. + for k := uint32(0); k < numPaths; k++ { + + // If our min-heap of candidate paths is empty, then we can + // exit early. + if candidatePaths.Len() == 0 { + break + } + nextShortestPath := heap.Pop(&candidatePaths).(path).hops + shortestPaths = append(shortestPaths, nextShortestPath) + } + + return shortestPaths, nil +} + +// findKPaths implements a k-shortest paths algorithm to find all the reachable // paths between the passed source and target. The algorithm will continue to // traverse the graph until all possible candidate paths have been depleted. // This function implements a modified version of Yen's. To find each path @@ -813,56 +1216,41 @@ func findPath(g *graphParams, r *restrictParams, // make our inner path finding algorithm aware of our k-shortest paths // algorithm, rather than attempting to use an unmodified path finding // algorithm in a block box manner. -func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph, +func findKPaths(g *graphParams, r *restrictParams, source *channeldb.LightningNode, target *btcec.PublicKey, - amt lnwire.MilliSatoshi, feeLimit lnwire.MilliSatoshi, numPaths uint32, - bandwidthHints map[uint64]lnwire.MilliSatoshi) ([][]*channeldb.ChannelEdgePolicy, error) { + amt lnwire.MilliSatoshi, + startingPath []*channeldb.ChannelEdgePolicy, + numPaths uint32) ([][]*channeldb.ChannelEdgePolicy, error) { - ignoredEdges := make(map[edgeLocator]struct{}) - ignoredVertexes := make(map[Vertex]struct{}) + sourceVertex := Vertex(source.PubKeyBytes) // TODO(roasbeef): modifying ordering within heap to eliminate final // sorting step? var ( shortestPaths [][]*channeldb.ChannelEdgePolicy candidatePaths pathHeap + validPathsNum uint32 ) - - // First we'll find a single shortest path from the source (our - // selfNode) to the target destination that's capable of carrying amt - // satoshis along the path before fees are calculated. - startingPath, err := findPath( - &graphParams{ - tx: tx, - graph: graph, - bandwidthHints: bandwidthHints, - }, - &restrictParams{ - ignoredNodes: ignoredVertexes, - ignoredEdges: ignoredEdges, - feeLimit: feeLimit, - }, - source, target, amt, - ) - if err != nil { - log.Errorf("Unable to find path: %v", err) - return nil, err - } + heap.Init(&candidatePaths) // Manually insert a "self" edge emanating from ourselves. This // self-edge is required in order for the path finding algorithm to // function properly. - firstPath := make([]*channeldb.ChannelEdgePolicy, 0, len(startingPath)+1) + firstPath := make([]*channeldb.ChannelEdgePolicy, 0, + len(startingPath)+1) firstPath = append(firstPath, &channeldb.ChannelEdgePolicy{ Node: source, }) firstPath = append(firstPath, startingPath...) + if len(firstPath) <= HopLimit+1 { + validPathsNum++ + } shortestPaths = append(shortestPaths, firstPath) // While we still have candidate paths to explore we'll keep exploring // the sub-graphs created to find the next k-th shortest path. - for k := uint32(1); k < numPaths; k++ { + for k := uint32(1); validPathsNum < numPaths; k++ { prevShortest := shortestPaths[k-1] // We'll examine each edge in the previous iteration's shortest @@ -873,8 +1261,12 @@ func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph, // we'll exclude from the next path finding attempt. // These are required to ensure the paths are unique // and loopless. - ignoredEdges = make(map[edgeLocator]struct{}) - ignoredVertexes = make(map[Vertex]struct{}) + ignoredEdges := make(map[edgeLocator]struct{}) + // Make sure to respect globally ignored edges. + for k, v := range r.ignoredEdges { + ignoredEdges[k] = v + } + ignoredVertexes := make(map[Vertex]struct{}) // Our spur node is the i-th node in the prior shortest // path, and our root path will be all nodes in the @@ -916,15 +1308,12 @@ func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph, // root path removed, we'll attempt to find another // shortest path from the spur node to the destination. spurPath, err := findPath( - &graphParams{ - tx: tx, - graph: graph, - bandwidthHints: bandwidthHints, - }, + g, &restrictParams{ - ignoredNodes: ignoredVertexes, - ignoredEdges: ignoredEdges, - feeLimit: feeLimit, + ignoredNodes: ignoredVertexes, + ignoredEdges: ignoredEdges, + feeLimit: r.feeLimit, + stopAtMaxHopsExceeded: true, }, spurNode, target, amt, ) @@ -932,13 +1321,21 @@ func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph, // the next round. if IsError(err, ErrNoPathFound) { continue - } else if err != nil { + } else if err != nil && !IsError(err, ErrMaxHopsExceeded) { return nil, err } // Create the new combined path by concatenating the // rootPath to the spurPath. newPathLen := len(rootPath) + len(spurPath) + if newPathLen > HopLimit+1 && validPathsNum > 0 { + // Cannot provide alternate paths in presence of + // shortest paths which are above hop limit. This + // is a potential for DoS attack on computing + // resources. + break + } + newPath := path{ hops: make([]*channeldb.ChannelEdgePolicy, 0, newPathLen), dist: newPathLen, @@ -963,8 +1360,29 @@ func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph, // path in our set of candidate paths and add it to our // shortestPaths list as the *next* shortest path. nextShortestPath := heap.Pop(&candidatePaths).(path).hops + if len(nextShortestPath) <= HopLimit+1 { + validPathsNum++ + } shortestPaths = append(shortestPaths, nextShortestPath) } - return shortestPaths, nil + // Filter out too-long paths. + fShortestPaths := shortestPaths[:0] + for _, path := range shortestPaths { + if len(path) <= HopLimit+1 { + fShortestPaths = append(fShortestPaths, path) + } + } + + // Pop the first artificially added edge if its not the first path + // segment. + if g.originVertex != nil && sourceVertex != *g.originVertex { + for i, path := range fShortestPaths { + path[0] = nil + path = path[1:] + fShortestPaths[i] = path + } + } + + return fShortestPaths, nil } diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index ce4e1a3f4c..c5989c421f 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "io/ioutil" - "math" "math/big" "net" "os" @@ -40,11 +39,6 @@ const ( // implementations will use in order to ensure that they're calculating // the payload for each hop in path properly. specExampleFilePath = "testdata/spec_example.json" - - // noFeeLimit is the maximum value of a payment through Lightning. We - // can use this value to signal there is no fee limit since payments - // should never be larger than this. - noFeeLimit = lnwire.MilliSatoshi(math.MaxUint32) ) var ( @@ -944,8 +938,8 @@ func TestKShortestPathFinding(t *testing.T) { paymentAmt := lnwire.NewMSatFromSatoshis(100) target := graph.aliasMap["luoji"] paths, err := findPaths( - nil, graph.graph, sourceNode, target, paymentAmt, noFeeLimit, 100, - nil, + nil, graph.graph, sourceNode, target, paymentAmt, noFeeLimit, + 100, nil, nil, ) if err != nil { t.Fatalf("unable to find paths between roasbeef and "+ @@ -1242,8 +1236,10 @@ func TestNewRoute(t *testing.T) { } } +// TestNewRoutePathTooLong tests that too-long paths are handled correctly; that +// path with 20 hops are valid while paths with 21 hops are rejected. func TestNewRoutePathTooLong(t *testing.T) { - t.Skip() + t.Parallel() // Ensure that potential paths which are over the maximum hop-limit are // rejected. @@ -1296,11 +1292,93 @@ func TestNewRoutePathTooLong(t *testing.T) { sourceNode, target, paymentAmt, ) if err == nil { - t.Fatalf("should not have been able to find path, supposed to be "+ - "greater than 20 hops, found route with %v hops", + t.Fatalf("should not have been able to find path, supposed to "+ + "be greater than 20 hops, found route with %v hops", len(path)) } + if !IsError(err, ErrMaxHopsExceeded) { + t.Fatalf("expected route too long error, got %v instead", err) + } + + // Add another vertex "gollum" connecting "inez" and "rick", providing an + // alternate path with smaller number of hops to "vincent" (14), but with + // higher total fees. Check that the new path is found. + gollumPubKeyHex := "03dd46ff29a6941b4a2607525b043ec9b020b3f318a1bf281536fd7011ec59c882" + gollumPubKeyBytes, err := hex.DecodeString(gollumPubKeyHex) + if err != nil { + t.Fatalf("unable to decode public key: %v", err) + } + gollumPubKey, err := btcec.ParsePubKey(gollumPubKeyBytes, btcec.S256()) + if err != nil { + t.Fatalf("unable to parse public key from bytes: %v", err) + } + + gollum := &channeldb.LightningNode{} + gollum.AddPubKey(gollumPubKey) + gollum.Alias = "gollum" + graph.aliasMap["gollum"] = gollumPubKey + + // Select high fees on the gollum edges. + _, edge, _, err := graph.graph.FetchChannelEdgesByID(12345) + if err != nil { + t.Fatalf("unable to fetch edge: %v", err) + } + if edge == nil { + t.Fatalf("unable to fetch edge: %v", err) + } + hugeBaseFee := edge.FeeBaseMSat * 100 + hugeFeeRate := edge.FeeProportionalMillionths * 100 + + // Create the channel edge going from inez to gollum, and from + // gollum to rick and include them in our map of additional edges. + inezToGollum := &channeldb.ChannelEdgePolicy{ + Node: gollum, + ChannelID: 222, + FeeBaseMSat: hugeBaseFee, + FeeProportionalMillionths: hugeFeeRate, + TimeLockDelta: 144, + } + + rick, err := graph.graph.FetchLightningNode(graph.aliasMap["rick"]) + if err != nil { + t.Fatalf("unable to retrieve %s node: %v", "rick", err) + } + + gollumToRick := &channeldb.ChannelEdgePolicy{ + Node: rick, + ChannelID: 223, + FeeBaseMSat: hugeBaseFee, + FeeProportionalMillionths: hugeFeeRate, + TimeLockDelta: 144, + } + + additionalEdges := map[Vertex][]*channeldb.ChannelEdgePolicy{ + NewVertex(graph.aliasMap["inez"]): {inezToGollum}, + NewVertex(graph.aliasMap["gollum"]): {gollumToRick}, + } + + target = graph.aliasMap["vincent"] + path, err = findPath( + &graphParams{ + graph: graph.graph, + additionalEdges: additionalEdges, + }, + &restrictParams{ + ignoredNodes: ignoredVertexes, + ignoredEdges: ignoredEdges, + feeLimit: noFeeLimit, + }, + sourceNode, target, paymentAmt, + ) + + if err != nil { + t.Fatalf("path should have been found") + } + + if len(path) != 14 { + t.Fatalf("expected %v hops, got %v hops", 14, len(path)) + } } func TestPathNotAvailable(t *testing.T) { @@ -1704,7 +1782,7 @@ func TestPathFindSpecExample(t *testing.T) { // Query for a route of 4,999,999 mSAT to carol. carol := ctx.aliases["C"] const amt lnwire.MilliSatoshi = 4999999 - routes, err := ctx.router.FindRoutes(carol, amt, noFeeLimit, 100) + routes, err := ctx.router.FindRoutes(carol, amt, noFeeLimit, nil, 100) if err != nil { t.Fatalf("unable to find route: %v", err) } @@ -1765,7 +1843,7 @@ func TestPathFindSpecExample(t *testing.T) { // We'll now request a route from A -> B -> C. ctx.router.routeCache = make(map[routeTuple][]*Route) - routes, err = ctx.router.FindRoutes(carol, amt, noFeeLimit, 100) + routes, err = ctx.router.FindRoutes(carol, amt, noFeeLimit, nil, 100) if err != nil { t.Fatalf("unable to find routes: %v", err) } diff --git a/routing/router.go b/routing/router.go index 7ffe7727a8..87fab29b0e 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1387,8 +1387,8 @@ func pathsToFeeSortedRoutes(source Vertex, paths [][]*channeldb.ChannelEdgePolic // route that will be ranked the highest is the one with the lowest cumulative // fee along the route. func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey, - amt, feeLimit lnwire.MilliSatoshi, numPaths uint32, - finalExpiry ...uint16) ([]*Route, error) { + amt, feeLimit lnwire.MilliSatoshi, pegs []HopPeg, + numPaths uint32, finalExpiry ...uint16) ([]*Route, error) { var finalCLTVDelta uint16 if len(finalExpiry) == 0 { @@ -1403,18 +1403,21 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey, // Before attempting to perform a series of graph traversals to find // the k-shortest paths to the destination, we'll first consult our // path cache - rt := newRouteTuple(amt, dest) - r.routeCacheMtx.RLock() - routes, ok := r.routeCache[rt] - r.routeCacheMtx.RUnlock() - - // If we already have a cached route, and it contains at least the - // number of paths requested, then we'll return it directly as there's - // no need to repeat the computation. - if ok && uint32(len(routes)) >= numPaths { - return routes, nil + var rt routeTuple + if len(pegs) == 0 { + // Pegged routes are not cached. + rt = newRouteTuple(amt, dest) + r.routeCacheMtx.RLock() + routes, ok := r.routeCache[rt] + r.routeCacheMtx.RUnlock() + + // If we already have a cached route, and it contains at least the + // number of paths requested, then we'll return it directly as there's + // no need to repeat the computation. + if ok && uint32(len(routes)) >= numPaths { + return routes, nil + } } - // If we don't have a set of routes cached, we'll query the graph for a // set of potential routes to the destination node that can support our // payment amount. If no such routes can be found then an error will be @@ -1430,6 +1433,25 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey, return nil, newErrf(ErrTargetNotInNetwork, "target not found") } + // Check that pegs are known and that there aren't too many of them. + if len(pegs) > HopLimit-2 { + return nil, newErr(ErrMaxHopsExceeded, "potential path has "+ + "too many hops") + } + for _, peg := range pegs { + pegVertex := NewVertex(peg.NodeID) + _, exists, err := r.cfg.Graph.HasLightningNode(pegVertex) + if err != nil { + return nil, err + } else if !exists { + log.Debugf("Peg %x is not in known graph", + peg.NodeID.SerializeCompressed()) + return nil, newErrf(ErrPegNotInNetwork, + "pegged node not found") + } + // TODO (bluetegu) add check for channels + } + // We'll also fetch the current block height so we can properly // calculate the required HTLC time locks within the route. _, currentHeight, err := r.cfg.Chain.GetBestBlock() @@ -1458,7 +1480,7 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey, // our source to the destination. shortestPaths, err := findPaths( tx, r.cfg.Graph, r.selfNode, target, amt, feeLimit, numPaths, - bandwidthHints, + bandwidthHints, pegs, ) if err != nil { tx.Rollback() @@ -1489,10 +1511,11 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey, // Populate the cache with this set of fresh routes so we can reuse // them in the future. - r.routeCacheMtx.Lock() - r.routeCache[rt] = validRoutes - r.routeCacheMtx.Unlock() - + if len(pegs) == 0 { + r.routeCacheMtx.Lock() + r.routeCache[rt] = validRoutes + r.routeCacheMtx.Unlock() + } return validRoutes, nil } diff --git a/routing/router_test.go b/routing/router_test.go index e39ed31386..365f4a7b9b 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -5,6 +5,7 @@ import ( "fmt" "image/color" "math/rand" + "reflect" "strings" "testing" "time" @@ -183,7 +184,7 @@ func TestFindRoutesFeeSorting(t *testing.T) { paymentAmt := lnwire.NewMSatFromSatoshis(100) target := ctx.aliases["luoji"] routes, err := ctx.router.FindRoutes( - target, paymentAmt, noFeeLimit, defaultNumRoutes, + target, paymentAmt, noFeeLimit, nil, defaultNumRoutes, DefaultFinalCLTVDelta, ) if err != nil { @@ -242,7 +243,7 @@ func TestFindRoutesWithFeeLimit(t *testing.T) { feeLimit := lnwire.NewMSatFromSatoshis(10) routes, err := ctx.router.FindRoutes( - target, paymentAmt, feeLimit, defaultNumRoutes, + target, paymentAmt, feeLimit, nil, defaultNumRoutes, DefaultFinalCLTVDelta, ) if err != nil { @@ -1221,7 +1222,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { paymentAmt := lnwire.NewMSatFromSatoshis(100) targetNode := priv2.PubKey() routes, err := ctx.router.FindRoutes( - targetNode, paymentAmt, noFeeLimit, defaultNumRoutes, + targetNode, paymentAmt, noFeeLimit, nil, defaultNumRoutes, DefaultFinalCLTVDelta, ) if err != nil { @@ -1266,7 +1267,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { // Should still be able to find the routes, and the info should be // updated. routes, err = ctx.router.FindRoutes( - targetNode, paymentAmt, noFeeLimit, defaultNumRoutes, + targetNode, paymentAmt, noFeeLimit, nil, defaultNumRoutes, DefaultFinalCLTVDelta, ) if err != nil { @@ -2152,3 +2153,447 @@ func TestEmptyRoutesGenerateSphinxPacket(t *testing.T) { t.Fatalf("expected empty hops error: instead got: %v", err) } } + +// routre2String prepares a string for printing an expected set of paths. +func route2String(route [][]string) (p string) { + for _, r := range route { + p += "\n" + p += strings.Join(r, "->") + } + return p + "\n" +} + +// routes2Strings returns a string representation of the routes' paths. +func routes2Strings(routes []*Route, ctx *testCtx) (s [][]string) { + for i := 0; i < len(routes); i++ { + ss := make([]string, len(routes[i].Hops)) + for j, hop := range routes[i].Hops { + ss[j] = fmt.Sprintf("(%d)%s", + hop.ChannelID, + getAliasFromPubKey( + hop.PubKeyBytes[:], + ctx.aliases, + ), + ) + } + s = append(s, ss) + } + return s +} + +// checkRouteFees checks the actual routes' total fees is as expected. +func checkRouteFees(routes []*Route, + expectedFees []lnwire.MilliSatoshi, + t *testing.T) { + + for i := 0; i < len(expectedFees); i++ { + if routes[i].TotalFees != expectedFees[i] { + t.Fatalf("route %d: expected %v MSat total fee, "+ + "instead got %v MSat", i+1, + expectedFees[i], + routes[i].TotalFees) + + } + } +} + +// TestPeggedRouting tests route selection with pegged +// nodes and channels. Pegging restrict routing to pass through the pegged +// node (and optionally through a channel) while searching for a route +// between source and destination. +// The resulting route is composed of segments connecting between the pegged +// nodes. Each segment does not have loops, but the entire path may. The +// route selection assures that no edge will be transversed twice at the +// same direction. +// The alternate routes are stitched from N-1 shortest segment paths and +// one alternate segment path. +// +// ┌──────────┐ 20 ┌──────────┐ +// │ E │───────────────────│ D │ +// └──────────┘ 6 └──────────┘ +// | | | +// | | | d/e +// | 10 | 50 | 20 +// | 3 | 4 | 5 +// | | | +// ┌──────────┐ 60 ┌──────────┐ +// │ B │───────────────────│ C │ +// └──────────┘ 2 └──────────┘ +// | +// | +// | 30 +// | 1 +// | ┌──────────┐ +// └─────────│ A │ +// └──────────┘ +// +// The setup is build from symmetric channels whose base fee is +// marked and the fee rate is set to 0. The channel id between +// each node is marked below the rate. +// +// Test 1: +// Find routes from origin (A) to final destination (E) through D. +// Channel 5 disabled. +// A -> *D -> *E +// +// The expected routes are: +// r1: A -> B -> E -> D -> E total fees: 50 +// r2: A -> B -> C -> D -> E total fees: 130 +// +// Note that in r1, E is visited twice, before and after D. The +// pegging does not enforce order, i.e. it does not imply that D +// will be reached before E, rather that after D is reached, E +// will be reached. +// +// The following routes should not be returned: +// r1: A -> B -> E -> D -> E -> D -> E total fees: 90 +// r2: A -> B -> E -> D -> C -> B -> E +// reason: Edges cannot be transversed twice in the same direction. +// The following route is not returned: +// r1: A -> B -> C -> D -> C -> B -> E total fees: 230 +// Eventhough no edge is transversed twice at the same direction +// due to the route stitching selection. This route is similar to +// a route stiched from the 2nd best A -> D with the 2nd best +// D -> E. +// +// Test 2: +// Find routes from origin (A) back to itself through (C) and (E). +// Channel 5 disabled. +// A -> *C -> *E -> *A +// +// The expected routes are: +// r1: A -> B -> C -> B -> E -> B -> A total fees: 170 +// r2: A -> B -> C -> D -> E -> B -> A total fees: 170 +// +// Note that both routes have the same total fees. +// +// Test 3: +// Find routes back to origin (A) passign through node C through channel 4 +// Channel 5 disabled. +// A -> (4)C -> *A +// +// The expected routes are: +// r1: A -> B -> E -> D -> C -> B -> A total fees: 170 +// r1: A -> B -> E -> D -> C -> D -> E -> B -> A total fees: 190 +// r3: A -> B -> C -> D -> C -> B -> A total fees: 250 +// +// Test 4: +// Find routes back to origin (A) passing through node D through +// channel 6 and then node C through channel 4 +// Channel 5 disabled. +// A -> (6)D -> (4)C -> *A +// +// The expected routes are: +// A -> B -> E -> (6)D -> (4)C -> B -> A +// A -> B -> E -> (6)D -> (4)C -> D -> E -> B -> A +// A -> B -> C -> D -> E -> (6)D -> (4)C -> B -> A +// +// Test 5: +// Find routes back to origin (A) passing through node D through +// channel 6 and then node C through channel 4 +// Channel 5 enabled. +// A -> (6)D -> (4)C -> (2)B -> A +// +// The expected routes are: +// A -> B -> E -> (6)D -> (4)C -> (2)B -> A +// A -> B -> C -> (5)D -> E -> (6)D -> (4)C -> (2)B -> A +// A -> B -> C -> (4)D -> E -> (6)D -> (4)C -> (2)B -> A +// +func TestPeggedRouting(t *testing.T) { + t.Parallel() + + // Setup the node network. + // roasbeef is used instead of a, as createTestGraphFromChannels + // set roasbeef as source. + testChannels := []*testChannel{ + symmetricTestChannel("roasbeef", "b", 1000, &testChannelPolicy{ + Expiry: 144, + FeeBaseMsat: 30, + FeeRate: 0, + MinHTLC: 1, + }, 1), + symmetricTestChannel("b", "c", 1000, &testChannelPolicy{ + Expiry: 144, + FeeBaseMsat: 60, + FeeRate: 0, + MinHTLC: 1, + }, 2), + symmetricTestChannel("b", "e", 1000, &testChannelPolicy{ + Expiry: 144, + FeeBaseMsat: 10, + FeeRate: 0, + MinHTLC: 1, + }, 3), + symmetricTestChannel("c", "d", 1000, &testChannelPolicy{ + Expiry: 144, + FeeBaseMsat: 50, + FeeRate: 0, + MinHTLC: 1, + }, 4), + symmetricTestChannel("c", "d", 1000, &testChannelPolicy{ + Expiry: 144, + FeeBaseMsat: 20, + FeeRate: 0, + MinHTLC: 1, + }, 5), + symmetricTestChannel("d", "e", 1000, &testChannelPolicy{ + Expiry: 144, + FeeBaseMsat: 20, + FeeRate: 0, + MinHTLC: 1, + }, 6), + } + + testGraph, err := createTestGraphFromChannels(testChannels) + defer testGraph.cleanUp() + if err != nil { + t.Fatalf("unable to create graph: %v", err) + } + + const startingBlockHeight = 101 + + ctx, cleanUp, err := createTestCtxFromGraphInstance(startingBlockHeight, + testGraph) + + defer cleanUp() + if err != nil { + t.Fatalf("unable to create router: %v", err) + } + + // closure to enable/disable channel 5, connecting C to D with + // lower fee. + enableChan5 := func(en bool) { + channelID := uint64(5) + _, e1, e2, err := ctx.graph.FetchChannelEdgesByID(channelID) + if err != nil { + t.Fatalf("unable to fetch edge: %v", err) + } + if en { + e1.ChannelFlags &^= lnwire.ChanUpdateDisabled + e2.ChannelFlags &^= lnwire.ChanUpdateDisabled + } else { + e1.ChannelFlags |= lnwire.ChanUpdateDisabled + e2.ChannelFlags |= lnwire.ChanUpdateDisabled + } + if err := ctx.graph.UpdateEdgePolicy(e1); err != nil { + t.Fatalf("unable to update edge: %v", err) + } + if err := ctx.graph.UpdateEdgePolicy(e2); err != nil { + t.Fatalf("unable to update edge: %v", err) + } + } + + // disable channel 5 + enableChan5(false) + + // Test 1: A *-> D *-> E + target := ctx.aliases["e"] + peggedHops := []HopPeg{ + { + NodeID: ctx.aliases["d"], + }, + } + + amt := lnwire.NewMSatFromSatoshis(400) + // Find routes. + routes, err := ctx.router.FindRoutes(target, + amt, noFeeLimit, peggedHops, 10, DefaultFinalCLTVDelta, + ) + if err != nil { + t.Fatalf("failed to find routes: %v", err) + } + + // Check route paths. + var expectedSeq = [][]string{ + {"(1)b", "(3)e", "(6)d", "(6)e"}, + {"(1)b", "(2)c", "(4)d", "(6)e"}, + } + actualSeq := routes2Strings(routes, ctx) + if !reflect.DeepEqual(expectedSeq, actualSeq) { + t.Fatalf("incorrect route: expected: %sinstead got: %s", + route2String(expectedSeq), + route2String(actualSeq), + ) + } + + // Check route fees + var expectedFees = []lnwire.MilliSatoshi{ + 50, + 130, + } + checkRouteFees(routes, expectedFees, t) + + // Test 2: A -> *C -> *E -> *A + target = ctx.aliases["roasbeef"] + peggedHops = []HopPeg{ + { + NodeID: ctx.aliases["c"], + }, + { + NodeID: ctx.aliases["e"], + }, + } + + amt = lnwire.NewMSatFromSatoshis(400) + // Find routes. + routes, err = ctx.router.FindRoutes(target, + amt, noFeeLimit, peggedHops, 10, DefaultFinalCLTVDelta, + ) + if err != nil { + t.Fatalf("failed to find routes: %v", err) + } + + // Check route paths. + expectedSeq = [][]string{ + {"(1)b", "(2)c", "(2)b", "(3)e", "(3)b", "(1)roasbeef"}, + {"(1)b", "(2)c", "(4)d", "(6)e", "(3)b", "(1)roasbeef"}, + } + actualSeq = routes2Strings(routes, ctx) + if !reflect.DeepEqual(expectedSeq, actualSeq) { + t.Fatalf("incorrect route: expected: %sinstead got: %s", + route2String(expectedSeq), + route2String(actualSeq), + ) + } + + // Check route fees + expectedFees = []lnwire.MilliSatoshi{ + 170, + 170, + } + checkRouteFees(routes, expectedFees, t) + + // Test 3: A -> (4)C -> A + target = ctx.aliases["roasbeef"] + peggedHops = []HopPeg{ + { + NodeID: ctx.aliases["c"], + ChannelID: 4, + }, + } + + amt = lnwire.NewMSatFromSatoshis(400) + // Find routes. + routes, err = ctx.router.FindRoutes(target, + amt, noFeeLimit, peggedHops, 10, DefaultFinalCLTVDelta, + ) + if err != nil { + t.Fatalf("failed to find routes: %v", err) + } + + // Check route paths. + expectedSeq = [][]string{ + {"(1)b", "(3)e", "(6)d", "(4)c", "(2)b", "(1)roasbeef"}, + {"(1)b", "(3)e", "(6)d", "(4)c", "(4)d", "(6)e", "(3)b", "(1)roasbeef"}, + {"(1)b", "(2)c", "(4)d", "(4)c", "(2)b", "(1)roasbeef"}, + } + actualSeq = routes2Strings(routes, ctx) + if !reflect.DeepEqual(expectedSeq, actualSeq) { + t.Fatalf("incorrect route: expected: %sinstead got: %s", + route2String(expectedSeq), + route2String(actualSeq), + ) + } + + // Check route fees + expectedFees = []lnwire.MilliSatoshi{ + 170, + 190, + 250, + } + checkRouteFees(routes, expectedFees, t) + + // Test 4: A -> (6)D -> (4)C -> A + target = ctx.aliases["roasbeef"] + peggedHops = []HopPeg{ + { + NodeID: ctx.aliases["d"], + ChannelID: 6, + }, + { + NodeID: ctx.aliases["c"], + ChannelID: 4, + }, + } + + amt = lnwire.NewMSatFromSatoshis(400) + // Find routes. + routes, err = ctx.router.FindRoutes(target, + amt, noFeeLimit, peggedHops, 10, DefaultFinalCLTVDelta, + ) + if err != nil { + t.Fatalf("failed to find routes: %v", err) + } + + // Check route paths. + expectedSeq = [][]string{ + {"(1)b", "(3)e", "(6)d", "(4)c", "(2)b", "(1)roasbeef"}, + {"(1)b", "(3)e", "(6)d", "(4)c", "(4)d", "(6)e", "(3)b", "(1)roasbeef"}, + {"(1)b", "(2)c", "(4)d", "(6)e", "(6)d", "(4)c", "(2)b", "(1)roasbeef"}, + } + actualSeq = routes2Strings(routes, ctx) + if !reflect.DeepEqual(expectedSeq, actualSeq) { + t.Fatalf("incorrect route: expected: %sinstead got: %s", + route2String(expectedSeq), + route2String(actualSeq), + ) + } + + // Check route fees + expectedFees = []lnwire.MilliSatoshi{ + 170, + 190, + 290, + } + checkRouteFees(routes, expectedFees, t) + + // Test 5: A -> (6)D -> (4)C -> (2)B -> A + target = ctx.aliases["roasbeef"] + peggedHops = []HopPeg{ + { + NodeID: ctx.aliases["d"], + ChannelID: 6, + }, + { + NodeID: ctx.aliases["c"], + ChannelID: 4, + }, + { + NodeID: ctx.aliases["b"], + ChannelID: 2, + }, + } + // enable channel 5 + enableChan5(true) + + amt = lnwire.NewMSatFromSatoshis(400) + // Find routes. + routes, err = ctx.router.FindRoutes(target, + amt, noFeeLimit, peggedHops, 10, DefaultFinalCLTVDelta, + ) + if err != nil { + t.Fatalf("failed to find routes: %v", err) + } + + // Check route paths. + expectedSeq = [][]string{ + {"(1)b", "(3)e", "(6)d", "(4)c", "(2)b", "(1)roasbeef"}, + {"(1)b", "(2)c", "(5)d", "(6)e", "(6)d", "(4)c", "(2)b", "(1)roasbeef"}, + {"(1)b", "(2)c", "(4)d", "(6)e", "(6)d", "(4)c", "(2)b", "(1)roasbeef"}, + } + actualSeq = routes2Strings(routes, ctx) + if !reflect.DeepEqual(expectedSeq, actualSeq) { + t.Fatalf("incorrect route: expected: %sinstead got: %s", + route2String(expectedSeq), + route2String(actualSeq), + ) + } + + // Check route fees + expectedFees = []lnwire.MilliSatoshi{ + 170, + 260, + 290, + } + checkRouteFees(routes, expectedFees, t) +} diff --git a/routing/testdata/excessive_hops.json b/routing/testdata/excessive_hops.json index 4eff08d92c..9b8b7d313d 100644 --- a/routing/testdata/excessive_hops.json +++ b/routing/testdata/excessive_hops.json @@ -102,12 +102,12 @@ }, { "source": false, - "pubkey": "0369bca64993fce966745d32c09b882f668958d9bd7aabb60ba35ef1884013be1d", + "pubkey": "0367cec75158a4129177bfb8b269cb586efe93d751b43800d456485e81c2620ca6", "alias": "ursula" }, { "source": false, - "pubkey": "0367cec75158a4129177bfb8b269cb586efe93d751b43800d456485e81c2620ca6", + "pubkey": "0369bca64993fce966745d32c09b882f668958d9bd7aabb60ba35ef1884013be1d", "alias": "vincent" } ], @@ -119,9 +119,9 @@ "channel_point": "99dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -131,9 +131,9 @@ "channel_point": "79dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -143,9 +143,9 @@ "channel_point": "69dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -155,9 +155,9 @@ "channel_point": "59dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -167,9 +167,9 @@ "channel_point": "49dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -179,9 +179,9 @@ "channel_point": "39dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -191,9 +191,9 @@ "channel_point": "29dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -203,9 +203,9 @@ "channel_point": "19dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -215,21 +215,21 @@ "channel_point": "88dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { "node_1": "02727bfd298aa055a6419404931dfc1ccb4f0eb7c9660a7df346b93d0025df3ba1", "node_2": "0280c83b3eded413dcec12f7952410e2738f079bd9cbc9a7c462e32ed4d74bd5b7", - "channel_id": 12341, + "channel_id": 12341, "channel_point": "87dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -239,9 +239,9 @@ "channel_point": "86dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -251,9 +251,9 @@ "channel_point": "85dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -263,9 +263,9 @@ "channel_point": "84dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -275,9 +275,9 @@ "channel_point": "83dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -287,9 +287,9 @@ "channel_point": "82dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -299,9 +299,9 @@ "channel_point": "81dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -311,9 +311,9 @@ "channel_point": "80dc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -323,9 +323,9 @@ "channel_point": "89ec56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { @@ -335,33 +335,33 @@ "channel_point": "89fc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { "node_1": "0362002b8fbc1a799c839c8bcea43fce38a147467a00bc450414bbeab5c7a19efe", - "node_2": "0369bca64993fce966745d32c09b882f668958d9bd7aabb60ba35ef1884013be1d", + "node_2": "0367cec75158a4129177bfb8b269cb586efe93d751b43800d456485e81c2620ca6", "channel_id": 12445, "channel_point": "89cc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 }, { - "node_1": "0369bca64993fce966745d32c09b882f668958d9bd7aabb60ba35ef1884013be1d", - "node_2": "0367cec75158a4129177bfb8b269cb586efe93d751b43800d456485e81c2620ca6", + "node_1": "0367cec75158a4129177bfb8b269cb586efe93d751b43800d456485e81c2620ca6", + "node_2": "0369bca64993fce966745d32c09b882f668958d9bd7aabb60ba35ef1884013be1d", "channel_id": 12545, "channel_point": "89bc56859c6a082d15ba1a7f6cb6be3fea62e1746e2cb8497b1189155c21a233:0", "flags": 0, "expiry": 1, - "min_htlc": 1, + "min_htlc": 1, "fee_base_msat": 10, - "fee_rate": 0.001, + "fee_rate": 1, "capacity": 100000 } ] diff --git a/rpcserver.go b/rpcserver.go index d692974bfd..519098404d 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -4007,11 +4007,11 @@ func (r *rpcServer) QueryRoutes(ctx context.Context, ) if in.FinalCltvDelta == 0 { routes, findErr = r.server.chanRouter.FindRoutes( - pubKey, amtMSat, feeLimit, numRoutesIn, + pubKey, amtMSat, feeLimit, nil, numRoutesIn, ) } else { routes, findErr = r.server.chanRouter.FindRoutes( - pubKey, amtMSat, feeLimit, numRoutesIn, + pubKey, amtMSat, feeLimit, nil, numRoutesIn, uint16(in.FinalCltvDelta), ) } From e4f220626a9e1be429a18afcebebf474e6e71968 Mon Sep 17 00:00:00 2001 From: bluetegu Date: Thu, 7 Feb 2019 11:58:19 -0500 Subject: [PATCH 2/3] Add hop and route pegging to grpc and rpc server --- lnrpc/rpc.pb.go | 1236 +++++++++++++++++++++++++---------------------- lnrpc/rpc.proto | 20 + rpcserver.go | 27 +- 3 files changed, 715 insertions(+), 568 deletions(-) diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 64cc5dec43..fe6d66ad99 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -49,7 +49,7 @@ func (x AddressType) String() string { return proto.EnumName(AddressType_name, int32(x)) } func (AddressType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{0} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{0} } type ChannelCloseSummary_ClosureType int32 @@ -84,7 +84,7 @@ func (x ChannelCloseSummary_ClosureType) String() string { return proto.EnumName(ChannelCloseSummary_ClosureType_name, int32(x)) } func (ChannelCloseSummary_ClosureType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{39, 0} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{39, 0} } type ChannelEventUpdate_UpdateType int32 @@ -113,7 +113,7 @@ func (x ChannelEventUpdate_UpdateType) String() string { return proto.EnumName(ChannelEventUpdate_UpdateType_name, int32(x)) } func (ChannelEventUpdate_UpdateType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{60, 0} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{60, 0} } type Invoice_InvoiceState int32 @@ -139,7 +139,7 @@ func (x Invoice_InvoiceState) String() string { return proto.EnumName(Invoice_InvoiceState_name, int32(x)) } func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{89, 0} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{91, 0} } type GenSeedRequest struct { @@ -160,7 +160,7 @@ func (m *GenSeedRequest) Reset() { *m = GenSeedRequest{} } func (m *GenSeedRequest) String() string { return proto.CompactTextString(m) } func (*GenSeedRequest) ProtoMessage() {} func (*GenSeedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{0} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{0} } func (m *GenSeedRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GenSeedRequest.Unmarshal(m, b) @@ -215,7 +215,7 @@ func (m *GenSeedResponse) Reset() { *m = GenSeedResponse{} } func (m *GenSeedResponse) String() string { return proto.CompactTextString(m) } func (*GenSeedResponse) ProtoMessage() {} func (*GenSeedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{1} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{1} } func (m *GenSeedResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GenSeedResponse.Unmarshal(m, b) @@ -280,7 +280,7 @@ func (m *InitWalletRequest) Reset() { *m = InitWalletRequest{} } func (m *InitWalletRequest) String() string { return proto.CompactTextString(m) } func (*InitWalletRequest) ProtoMessage() {} func (*InitWalletRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{2} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{2} } func (m *InitWalletRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InitWalletRequest.Unmarshal(m, b) @@ -338,7 +338,7 @@ func (m *InitWalletResponse) Reset() { *m = InitWalletResponse{} } func (m *InitWalletResponse) String() string { return proto.CompactTextString(m) } func (*InitWalletResponse) ProtoMessage() {} func (*InitWalletResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{3} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{3} } func (m *InitWalletResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InitWalletResponse.Unmarshal(m, b) @@ -380,7 +380,7 @@ func (m *UnlockWalletRequest) Reset() { *m = UnlockWalletRequest{} } func (m *UnlockWalletRequest) String() string { return proto.CompactTextString(m) } func (*UnlockWalletRequest) ProtoMessage() {} func (*UnlockWalletRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{4} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{4} } func (m *UnlockWalletRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UnlockWalletRequest.Unmarshal(m, b) @@ -424,7 +424,7 @@ func (m *UnlockWalletResponse) Reset() { *m = UnlockWalletResponse{} } func (m *UnlockWalletResponse) String() string { return proto.CompactTextString(m) } func (*UnlockWalletResponse) ProtoMessage() {} func (*UnlockWalletResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{5} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{5} } func (m *UnlockWalletResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_UnlockWalletResponse.Unmarshal(m, b) @@ -462,7 +462,7 @@ func (m *ChangePasswordRequest) Reset() { *m = ChangePasswordRequest{} } func (m *ChangePasswordRequest) String() string { return proto.CompactTextString(m) } func (*ChangePasswordRequest) ProtoMessage() {} func (*ChangePasswordRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{6} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{6} } func (m *ChangePasswordRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChangePasswordRequest.Unmarshal(m, b) @@ -506,7 +506,7 @@ func (m *ChangePasswordResponse) Reset() { *m = ChangePasswordResponse{} func (m *ChangePasswordResponse) String() string { return proto.CompactTextString(m) } func (*ChangePasswordResponse) ProtoMessage() {} func (*ChangePasswordResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{7} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{7} } func (m *ChangePasswordResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChangePasswordResponse.Unmarshal(m, b) @@ -548,7 +548,7 @@ func (m *Utxo) Reset() { *m = Utxo{} } func (m *Utxo) String() string { return proto.CompactTextString(m) } func (*Utxo) ProtoMessage() {} func (*Utxo) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{8} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{8} } func (m *Utxo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Utxo.Unmarshal(m, b) @@ -636,7 +636,7 @@ func (m *Transaction) Reset() { *m = Transaction{} } func (m *Transaction) String() string { return proto.CompactTextString(m) } func (*Transaction) ProtoMessage() {} func (*Transaction) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{9} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{9} } func (m *Transaction) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Transaction.Unmarshal(m, b) @@ -722,7 +722,7 @@ func (m *GetTransactionsRequest) Reset() { *m = GetTransactionsRequest{} func (m *GetTransactionsRequest) String() string { return proto.CompactTextString(m) } func (*GetTransactionsRequest) ProtoMessage() {} func (*GetTransactionsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{10} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{10} } func (m *GetTransactionsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetTransactionsRequest.Unmarshal(m, b) @@ -754,7 +754,7 @@ func (m *TransactionDetails) Reset() { *m = TransactionDetails{} } func (m *TransactionDetails) String() string { return proto.CompactTextString(m) } func (*TransactionDetails) ProtoMessage() {} func (*TransactionDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{11} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{11} } func (m *TransactionDetails) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TransactionDetails.Unmarshal(m, b) @@ -795,7 +795,7 @@ func (m *FeeLimit) Reset() { *m = FeeLimit{} } func (m *FeeLimit) String() string { return proto.CompactTextString(m) } func (*FeeLimit) ProtoMessage() {} func (*FeeLimit) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{12} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{12} } func (m *FeeLimit) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeLimit.Unmarshal(m, b) @@ -955,7 +955,7 @@ func (m *SendRequest) Reset() { *m = SendRequest{} } func (m *SendRequest) String() string { return proto.CompactTextString(m) } func (*SendRequest) ProtoMessage() {} func (*SendRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{13} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{13} } func (m *SendRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendRequest.Unmarshal(m, b) @@ -1052,7 +1052,7 @@ func (m *SendResponse) Reset() { *m = SendResponse{} } func (m *SendResponse) String() string { return proto.CompactTextString(m) } func (*SendResponse) ProtoMessage() {} func (*SendResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{14} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{14} } func (m *SendResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendResponse.Unmarshal(m, b) @@ -1122,7 +1122,7 @@ func (m *SendToRouteRequest) Reset() { *m = SendToRouteRequest{} } func (m *SendToRouteRequest) String() string { return proto.CompactTextString(m) } func (*SendToRouteRequest) ProtoMessage() {} func (*SendToRouteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{15} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{15} } func (m *SendToRouteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendToRouteRequest.Unmarshal(m, b) @@ -1187,7 +1187,7 @@ func (m *ChannelPoint) Reset() { *m = ChannelPoint{} } func (m *ChannelPoint) String() string { return proto.CompactTextString(m) } func (*ChannelPoint) ProtoMessage() {} func (*ChannelPoint) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{16} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{16} } func (m *ChannelPoint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelPoint.Unmarshal(m, b) @@ -1333,7 +1333,7 @@ func (m *OutPoint) Reset() { *m = OutPoint{} } func (m *OutPoint) String() string { return proto.CompactTextString(m) } func (*OutPoint) ProtoMessage() {} func (*OutPoint) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{17} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{17} } func (m *OutPoint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_OutPoint.Unmarshal(m, b) @@ -1388,7 +1388,7 @@ func (m *LightningAddress) Reset() { *m = LightningAddress{} } func (m *LightningAddress) String() string { return proto.CompactTextString(m) } func (*LightningAddress) ProtoMessage() {} func (*LightningAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{18} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{18} } func (m *LightningAddress) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_LightningAddress.Unmarshal(m, b) @@ -1438,7 +1438,7 @@ func (m *SendManyRequest) Reset() { *m = SendManyRequest{} } func (m *SendManyRequest) String() string { return proto.CompactTextString(m) } func (*SendManyRequest) ProtoMessage() {} func (*SendManyRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{19} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{19} } func (m *SendManyRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendManyRequest.Unmarshal(m, b) @@ -1491,7 +1491,7 @@ func (m *SendManyResponse) Reset() { *m = SendManyResponse{} } func (m *SendManyResponse) String() string { return proto.CompactTextString(m) } func (*SendManyResponse) ProtoMessage() {} func (*SendManyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{20} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{20} } func (m *SendManyResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendManyResponse.Unmarshal(m, b) @@ -1541,7 +1541,7 @@ func (m *SendCoinsRequest) Reset() { *m = SendCoinsRequest{} } func (m *SendCoinsRequest) String() string { return proto.CompactTextString(m) } func (*SendCoinsRequest) ProtoMessage() {} func (*SendCoinsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{21} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{21} } func (m *SendCoinsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendCoinsRequest.Unmarshal(m, b) @@ -1608,7 +1608,7 @@ func (m *SendCoinsResponse) Reset() { *m = SendCoinsResponse{} } func (m *SendCoinsResponse) String() string { return proto.CompactTextString(m) } func (*SendCoinsResponse) ProtoMessage() {} func (*SendCoinsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{22} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{22} } func (m *SendCoinsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SendCoinsResponse.Unmarshal(m, b) @@ -1649,7 +1649,7 @@ func (m *ListUnspentRequest) Reset() { *m = ListUnspentRequest{} } func (m *ListUnspentRequest) String() string { return proto.CompactTextString(m) } func (*ListUnspentRequest) ProtoMessage() {} func (*ListUnspentRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{23} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{23} } func (m *ListUnspentRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListUnspentRequest.Unmarshal(m, b) @@ -1695,7 +1695,7 @@ func (m *ListUnspentResponse) Reset() { *m = ListUnspentResponse{} } func (m *ListUnspentResponse) String() string { return proto.CompactTextString(m) } func (*ListUnspentResponse) ProtoMessage() {} func (*ListUnspentResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{24} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{24} } func (m *ListUnspentResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListUnspentResponse.Unmarshal(m, b) @@ -1734,7 +1734,7 @@ func (m *NewAddressRequest) Reset() { *m = NewAddressRequest{} } func (m *NewAddressRequest) String() string { return proto.CompactTextString(m) } func (*NewAddressRequest) ProtoMessage() {} func (*NewAddressRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{25} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{25} } func (m *NewAddressRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NewAddressRequest.Unmarshal(m, b) @@ -1773,7 +1773,7 @@ func (m *NewAddressResponse) Reset() { *m = NewAddressResponse{} } func (m *NewAddressResponse) String() string { return proto.CompactTextString(m) } func (*NewAddressResponse) ProtoMessage() {} func (*NewAddressResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{26} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{26} } func (m *NewAddressResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NewAddressResponse.Unmarshal(m, b) @@ -1812,7 +1812,7 @@ func (m *SignMessageRequest) Reset() { *m = SignMessageRequest{} } func (m *SignMessageRequest) String() string { return proto.CompactTextString(m) } func (*SignMessageRequest) ProtoMessage() {} func (*SignMessageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{27} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{27} } func (m *SignMessageRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SignMessageRequest.Unmarshal(m, b) @@ -1851,7 +1851,7 @@ func (m *SignMessageResponse) Reset() { *m = SignMessageResponse{} } func (m *SignMessageResponse) String() string { return proto.CompactTextString(m) } func (*SignMessageResponse) ProtoMessage() {} func (*SignMessageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{28} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{28} } func (m *SignMessageResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SignMessageResponse.Unmarshal(m, b) @@ -1892,7 +1892,7 @@ func (m *VerifyMessageRequest) Reset() { *m = VerifyMessageRequest{} } func (m *VerifyMessageRequest) String() string { return proto.CompactTextString(m) } func (*VerifyMessageRequest) ProtoMessage() {} func (*VerifyMessageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{29} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{29} } func (m *VerifyMessageRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VerifyMessageRequest.Unmarshal(m, b) @@ -1940,7 +1940,7 @@ func (m *VerifyMessageResponse) Reset() { *m = VerifyMessageResponse{} } func (m *VerifyMessageResponse) String() string { return proto.CompactTextString(m) } func (*VerifyMessageResponse) ProtoMessage() {} func (*VerifyMessageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{30} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{30} } func (m *VerifyMessageResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VerifyMessageResponse.Unmarshal(m, b) @@ -1989,7 +1989,7 @@ func (m *ConnectPeerRequest) Reset() { *m = ConnectPeerRequest{} } func (m *ConnectPeerRequest) String() string { return proto.CompactTextString(m) } func (*ConnectPeerRequest) ProtoMessage() {} func (*ConnectPeerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{31} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{31} } func (m *ConnectPeerRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConnectPeerRequest.Unmarshal(m, b) @@ -2033,7 +2033,7 @@ func (m *ConnectPeerResponse) Reset() { *m = ConnectPeerResponse{} } func (m *ConnectPeerResponse) String() string { return proto.CompactTextString(m) } func (*ConnectPeerResponse) ProtoMessage() {} func (*ConnectPeerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{32} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{32} } func (m *ConnectPeerResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConnectPeerResponse.Unmarshal(m, b) @@ -2065,7 +2065,7 @@ func (m *DisconnectPeerRequest) Reset() { *m = DisconnectPeerRequest{} } func (m *DisconnectPeerRequest) String() string { return proto.CompactTextString(m) } func (*DisconnectPeerRequest) ProtoMessage() {} func (*DisconnectPeerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{33} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{33} } func (m *DisconnectPeerRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DisconnectPeerRequest.Unmarshal(m, b) @@ -2102,7 +2102,7 @@ func (m *DisconnectPeerResponse) Reset() { *m = DisconnectPeerResponse{} func (m *DisconnectPeerResponse) String() string { return proto.CompactTextString(m) } func (*DisconnectPeerResponse) ProtoMessage() {} func (*DisconnectPeerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{34} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{34} } func (m *DisconnectPeerResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DisconnectPeerResponse.Unmarshal(m, b) @@ -2136,7 +2136,7 @@ func (m *HTLC) Reset() { *m = HTLC{} } func (m *HTLC) String() string { return proto.CompactTextString(m) } func (*HTLC) ProtoMessage() {} func (*HTLC) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{35} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{35} } func (m *HTLC) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HTLC.Unmarshal(m, b) @@ -2250,7 +2250,7 @@ func (m *Channel) Reset() { *m = Channel{} } func (m *Channel) String() string { return proto.CompactTextString(m) } func (*Channel) ProtoMessage() {} func (*Channel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{36} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{36} } func (m *Channel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Channel.Unmarshal(m, b) @@ -2410,7 +2410,7 @@ func (m *ListChannelsRequest) Reset() { *m = ListChannelsRequest{} } func (m *ListChannelsRequest) String() string { return proto.CompactTextString(m) } func (*ListChannelsRequest) ProtoMessage() {} func (*ListChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{37} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{37} } func (m *ListChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListChannelsRequest.Unmarshal(m, b) @@ -2470,7 +2470,7 @@ func (m *ListChannelsResponse) Reset() { *m = ListChannelsResponse{} } func (m *ListChannelsResponse) String() string { return proto.CompactTextString(m) } func (*ListChannelsResponse) ProtoMessage() {} func (*ListChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{38} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{38} } func (m *ListChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListChannelsResponse.Unmarshal(m, b) @@ -2527,7 +2527,7 @@ func (m *ChannelCloseSummary) Reset() { *m = ChannelCloseSummary{} } func (m *ChannelCloseSummary) String() string { return proto.CompactTextString(m) } func (*ChannelCloseSummary) ProtoMessage() {} func (*ChannelCloseSummary) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{39} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{39} } func (m *ChannelCloseSummary) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelCloseSummary.Unmarshal(m, b) @@ -2633,7 +2633,7 @@ func (m *ClosedChannelsRequest) Reset() { *m = ClosedChannelsRequest{} } func (m *ClosedChannelsRequest) String() string { return proto.CompactTextString(m) } func (*ClosedChannelsRequest) ProtoMessage() {} func (*ClosedChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{40} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{40} } func (m *ClosedChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelsRequest.Unmarshal(m, b) @@ -2706,7 +2706,7 @@ func (m *ClosedChannelsResponse) Reset() { *m = ClosedChannelsResponse{} func (m *ClosedChannelsResponse) String() string { return proto.CompactTextString(m) } func (*ClosedChannelsResponse) ProtoMessage() {} func (*ClosedChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{41} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{41} } func (m *ClosedChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelsResponse.Unmarshal(m, b) @@ -2759,7 +2759,7 @@ func (m *Peer) Reset() { *m = Peer{} } func (m *Peer) String() string { return proto.CompactTextString(m) } func (*Peer) ProtoMessage() {} func (*Peer) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{42} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{42} } func (m *Peer) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Peer.Unmarshal(m, b) @@ -2845,7 +2845,7 @@ func (m *ListPeersRequest) Reset() { *m = ListPeersRequest{} } func (m *ListPeersRequest) String() string { return proto.CompactTextString(m) } func (*ListPeersRequest) ProtoMessage() {} func (*ListPeersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{43} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{43} } func (m *ListPeersRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPeersRequest.Unmarshal(m, b) @@ -2877,7 +2877,7 @@ func (m *ListPeersResponse) Reset() { *m = ListPeersResponse{} } func (m *ListPeersResponse) String() string { return proto.CompactTextString(m) } func (*ListPeersResponse) ProtoMessage() {} func (*ListPeersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{44} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{44} } func (m *ListPeersResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPeersResponse.Unmarshal(m, b) @@ -2914,7 +2914,7 @@ func (m *GetInfoRequest) Reset() { *m = GetInfoRequest{} } func (m *GetInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetInfoRequest) ProtoMessage() {} func (*GetInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{45} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{45} } func (m *GetInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetInfoRequest.Unmarshal(m, b) @@ -2974,7 +2974,7 @@ func (m *GetInfoResponse) Reset() { *m = GetInfoResponse{} } func (m *GetInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetInfoResponse) ProtoMessage() {} func (*GetInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{46} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{46} } func (m *GetInfoResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetInfoResponse.Unmarshal(m, b) @@ -3107,7 +3107,7 @@ func (m *Chain) Reset() { *m = Chain{} } func (m *Chain) String() string { return proto.CompactTextString(m) } func (*Chain) ProtoMessage() {} func (*Chain) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{47} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{47} } func (m *Chain) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Chain.Unmarshal(m, b) @@ -3154,7 +3154,7 @@ func (m *ConfirmationUpdate) Reset() { *m = ConfirmationUpdate{} } func (m *ConfirmationUpdate) String() string { return proto.CompactTextString(m) } func (*ConfirmationUpdate) ProtoMessage() {} func (*ConfirmationUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{48} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{48} } func (m *ConfirmationUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ConfirmationUpdate.Unmarshal(m, b) @@ -3206,7 +3206,7 @@ func (m *ChannelOpenUpdate) Reset() { *m = ChannelOpenUpdate{} } func (m *ChannelOpenUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelOpenUpdate) ProtoMessage() {} func (*ChannelOpenUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{49} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{49} } func (m *ChannelOpenUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelOpenUpdate.Unmarshal(m, b) @@ -3245,7 +3245,7 @@ func (m *ChannelCloseUpdate) Reset() { *m = ChannelCloseUpdate{} } func (m *ChannelCloseUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelCloseUpdate) ProtoMessage() {} func (*ChannelCloseUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{50} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{50} } func (m *ChannelCloseUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelCloseUpdate.Unmarshal(m, b) @@ -3300,7 +3300,7 @@ func (m *CloseChannelRequest) Reset() { *m = CloseChannelRequest{} } func (m *CloseChannelRequest) String() string { return proto.CompactTextString(m) } func (*CloseChannelRequest) ProtoMessage() {} func (*CloseChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{51} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{51} } func (m *CloseChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CloseChannelRequest.Unmarshal(m, b) @@ -3362,7 +3362,7 @@ func (m *CloseStatusUpdate) Reset() { *m = CloseStatusUpdate{} } func (m *CloseStatusUpdate) String() string { return proto.CompactTextString(m) } func (*CloseStatusUpdate) ProtoMessage() {} func (*CloseStatusUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{52} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{52} } func (m *CloseStatusUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CloseStatusUpdate.Unmarshal(m, b) @@ -3505,7 +3505,7 @@ func (m *PendingUpdate) Reset() { *m = PendingUpdate{} } func (m *PendingUpdate) String() string { return proto.CompactTextString(m) } func (*PendingUpdate) ProtoMessage() {} func (*PendingUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{53} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{53} } func (m *PendingUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingUpdate.Unmarshal(m, b) @@ -3571,7 +3571,7 @@ func (m *OpenChannelRequest) Reset() { *m = OpenChannelRequest{} } func (m *OpenChannelRequest) String() string { return proto.CompactTextString(m) } func (*OpenChannelRequest) ProtoMessage() {} func (*OpenChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{54} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{54} } func (m *OpenChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_OpenChannelRequest.Unmarshal(m, b) @@ -3682,7 +3682,7 @@ func (m *OpenStatusUpdate) Reset() { *m = OpenStatusUpdate{} } func (m *OpenStatusUpdate) String() string { return proto.CompactTextString(m) } func (*OpenStatusUpdate) ProtoMessage() {} func (*OpenStatusUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{55} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{55} } func (m *OpenStatusUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_OpenStatusUpdate.Unmarshal(m, b) @@ -3838,7 +3838,7 @@ func (m *PendingHTLC) Reset() { *m = PendingHTLC{} } func (m *PendingHTLC) String() string { return proto.CompactTextString(m) } func (*PendingHTLC) ProtoMessage() {} func (*PendingHTLC) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{56} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{56} } func (m *PendingHTLC) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingHTLC.Unmarshal(m, b) @@ -3910,7 +3910,7 @@ func (m *PendingChannelsRequest) Reset() { *m = PendingChannelsRequest{} func (m *PendingChannelsRequest) String() string { return proto.CompactTextString(m) } func (*PendingChannelsRequest) ProtoMessage() {} func (*PendingChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{57} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{57} } func (m *PendingChannelsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsRequest.Unmarshal(m, b) @@ -3950,7 +3950,7 @@ func (m *PendingChannelsResponse) Reset() { *m = PendingChannelsResponse func (m *PendingChannelsResponse) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse) ProtoMessage() {} func (*PendingChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{58} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{58} } func (m *PendingChannelsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse.Unmarshal(m, b) @@ -4022,7 +4022,7 @@ func (m *PendingChannelsResponse_PendingChannel) Reset() { func (m *PendingChannelsResponse_PendingChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_PendingChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{58, 0} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{58, 0} } func (m *PendingChannelsResponse_PendingChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_PendingChannel.Unmarshal(m, b) @@ -4109,7 +4109,7 @@ func (m *PendingChannelsResponse_PendingOpenChannel) String() string { } func (*PendingChannelsResponse_PendingOpenChannel) ProtoMessage() {} func (*PendingChannelsResponse_PendingOpenChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{58, 1} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{58, 1} } func (m *PendingChannelsResponse_PendingOpenChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_PendingOpenChannel.Unmarshal(m, b) @@ -4182,7 +4182,7 @@ func (m *PendingChannelsResponse_WaitingCloseChannel) String() string { } func (*PendingChannelsResponse_WaitingCloseChannel) ProtoMessage() {} func (*PendingChannelsResponse_WaitingCloseChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{58, 2} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{58, 2} } func (m *PendingChannelsResponse_WaitingCloseChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_WaitingCloseChannel.Unmarshal(m, b) @@ -4230,7 +4230,7 @@ func (m *PendingChannelsResponse_ClosedChannel) Reset() { *m = PendingCh func (m *PendingChannelsResponse_ClosedChannel) String() string { return proto.CompactTextString(m) } func (*PendingChannelsResponse_ClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{58, 3} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{58, 3} } func (m *PendingChannelsResponse_ClosedChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_ClosedChannel.Unmarshal(m, b) @@ -4294,7 +4294,7 @@ func (m *PendingChannelsResponse_ForceClosedChannel) String() string { } func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {} func (*PendingChannelsResponse_ForceClosedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{58, 4} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{58, 4} } func (m *PendingChannelsResponse_ForceClosedChannel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PendingChannelsResponse_ForceClosedChannel.Unmarshal(m, b) @@ -4373,7 +4373,7 @@ func (m *ChannelEventSubscription) Reset() { *m = ChannelEventSubscripti func (m *ChannelEventSubscription) String() string { return proto.CompactTextString(m) } func (*ChannelEventSubscription) ProtoMessage() {} func (*ChannelEventSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{59} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{59} } func (m *ChannelEventSubscription) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEventSubscription.Unmarshal(m, b) @@ -4410,7 +4410,7 @@ func (m *ChannelEventUpdate) Reset() { *m = ChannelEventUpdate{} } func (m *ChannelEventUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelEventUpdate) ProtoMessage() {} func (*ChannelEventUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{60} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{60} } func (m *ChannelEventUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEventUpdate.Unmarshal(m, b) @@ -4622,7 +4622,7 @@ func (m *WalletBalanceRequest) Reset() { *m = WalletBalanceRequest{} } func (m *WalletBalanceRequest) String() string { return proto.CompactTextString(m) } func (*WalletBalanceRequest) ProtoMessage() {} func (*WalletBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{61} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{61} } func (m *WalletBalanceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WalletBalanceRequest.Unmarshal(m, b) @@ -4658,7 +4658,7 @@ func (m *WalletBalanceResponse) Reset() { *m = WalletBalanceResponse{} } func (m *WalletBalanceResponse) String() string { return proto.CompactTextString(m) } func (*WalletBalanceResponse) ProtoMessage() {} func (*WalletBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{62} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{62} } func (m *WalletBalanceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WalletBalanceResponse.Unmarshal(m, b) @@ -4709,7 +4709,7 @@ func (m *ChannelBalanceRequest) Reset() { *m = ChannelBalanceRequest{} } func (m *ChannelBalanceRequest) String() string { return proto.CompactTextString(m) } func (*ChannelBalanceRequest) ProtoMessage() {} func (*ChannelBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{63} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{63} } func (m *ChannelBalanceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelBalanceRequest.Unmarshal(m, b) @@ -4743,7 +4743,7 @@ func (m *ChannelBalanceResponse) Reset() { *m = ChannelBalanceResponse{} func (m *ChannelBalanceResponse) String() string { return proto.CompactTextString(m) } func (*ChannelBalanceResponse) ProtoMessage() {} func (*ChannelBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{64} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{64} } func (m *ChannelBalanceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelBalanceResponse.Unmarshal(m, b) @@ -4791,7 +4791,10 @@ type QueryRoutesRequest struct { // This value can be represented either as a percentage of the amount being // sent, or as a fixed amount of the maximum fee the user is willing the pay to // send the payment. - FeeLimit *FeeLimit `protobuf:"bytes,5,opt,name=fee_limit,json=feeLimit,proto3" json:"fee_limit,omitempty"` + FeeLimit *FeeLimit `protobuf:"bytes,5,opt,name=fee_limit,json=feeLimit,proto3" json:"fee_limit,omitempty"` + // * + // An optional list of nodes and channels the route must pass through in that order. + RoutePeg *RoutePeg `protobuf:"bytes,6,opt,name=route_peg,json=routePeg,proto3" json:"route_peg,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -4801,7 +4804,7 @@ func (m *QueryRoutesRequest) Reset() { *m = QueryRoutesRequest{} } func (m *QueryRoutesRequest) String() string { return proto.CompactTextString(m) } func (*QueryRoutesRequest) ProtoMessage() {} func (*QueryRoutesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{65} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{65} } func (m *QueryRoutesRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryRoutesRequest.Unmarshal(m, b) @@ -4856,6 +4859,13 @@ func (m *QueryRoutesRequest) GetFeeLimit() *FeeLimit { return nil } +func (m *QueryRoutesRequest) GetRoutePeg() *RoutePeg { + if m != nil { + return m.RoutePeg + } + return nil +} + type QueryRoutesResponse struct { Routes []*Route `protobuf:"bytes,1,rep,name=routes,proto3" json:"routes,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -4867,7 +4877,7 @@ func (m *QueryRoutesResponse) Reset() { *m = QueryRoutesResponse{} } func (m *QueryRoutesResponse) String() string { return proto.CompactTextString(m) } func (*QueryRoutesResponse) ProtoMessage() {} func (*QueryRoutesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{66} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{66} } func (m *QueryRoutesResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QueryRoutesResponse.Unmarshal(m, b) @@ -4919,7 +4929,7 @@ func (m *Hop) Reset() { *m = Hop{} } func (m *Hop) String() string { return proto.CompactTextString(m) } func (*Hop) ProtoMessage() {} func (*Hop) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{67} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{67} } func (m *Hop) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Hop.Unmarshal(m, b) @@ -5040,7 +5050,7 @@ func (m *Route) Reset() { *m = Route{} } func (m *Route) String() string { return proto.CompactTextString(m) } func (*Route) ProtoMessage() {} func (*Route) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{68} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{68} } func (m *Route) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Route.Unmarshal(m, b) @@ -5116,7 +5126,7 @@ func (m *NodeInfoRequest) Reset() { *m = NodeInfoRequest{} } func (m *NodeInfoRequest) String() string { return proto.CompactTextString(m) } func (*NodeInfoRequest) ProtoMessage() {} func (*NodeInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{69} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{69} } func (m *NodeInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeInfoRequest.Unmarshal(m, b) @@ -5161,7 +5171,7 @@ func (m *NodeInfo) Reset() { *m = NodeInfo{} } func (m *NodeInfo) String() string { return proto.CompactTextString(m) } func (*NodeInfo) ProtoMessage() {} func (*NodeInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{70} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{70} } func (m *NodeInfo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeInfo.Unmarshal(m, b) @@ -5222,7 +5232,7 @@ func (m *LightningNode) Reset() { *m = LightningNode{} } func (m *LightningNode) String() string { return proto.CompactTextString(m) } func (*LightningNode) ProtoMessage() {} func (*LightningNode) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{71} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{71} } func (m *LightningNode) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_LightningNode.Unmarshal(m, b) @@ -5289,7 +5299,7 @@ func (m *NodeAddress) Reset() { *m = NodeAddress{} } func (m *NodeAddress) String() string { return proto.CompactTextString(m) } func (*NodeAddress) ProtoMessage() {} func (*NodeAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{72} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{72} } func (m *NodeAddress) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeAddress.Unmarshal(m, b) @@ -5338,7 +5348,7 @@ func (m *RoutingPolicy) Reset() { *m = RoutingPolicy{} } func (m *RoutingPolicy) String() string { return proto.CompactTextString(m) } func (*RoutingPolicy) ProtoMessage() {} func (*RoutingPolicy) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{73} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{73} } func (m *RoutingPolicy) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RoutingPolicy.Unmarshal(m, b) @@ -5421,7 +5431,7 @@ func (m *ChannelEdge) Reset() { *m = ChannelEdge{} } func (m *ChannelEdge) String() string { return proto.CompactTextString(m) } func (*ChannelEdge) ProtoMessage() {} func (*ChannelEdge) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{74} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{74} } func (m *ChannelEdge) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEdge.Unmarshal(m, b) @@ -5512,7 +5522,7 @@ func (m *ChannelGraphRequest) Reset() { *m = ChannelGraphRequest{} } func (m *ChannelGraphRequest) String() string { return proto.CompactTextString(m) } func (*ChannelGraphRequest) ProtoMessage() {} func (*ChannelGraphRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{75} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{75} } func (m *ChannelGraphRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelGraphRequest.Unmarshal(m, b) @@ -5554,7 +5564,7 @@ func (m *ChannelGraph) Reset() { *m = ChannelGraph{} } func (m *ChannelGraph) String() string { return proto.CompactTextString(m) } func (*ChannelGraph) ProtoMessage() {} func (*ChannelGraph) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{76} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{76} } func (m *ChannelGraph) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelGraph.Unmarshal(m, b) @@ -5603,7 +5613,7 @@ func (m *ChanInfoRequest) Reset() { *m = ChanInfoRequest{} } func (m *ChanInfoRequest) String() string { return proto.CompactTextString(m) } func (*ChanInfoRequest) ProtoMessage() {} func (*ChanInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{77} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{77} } func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChanInfoRequest.Unmarshal(m, b) @@ -5640,7 +5650,7 @@ func (m *NetworkInfoRequest) Reset() { *m = NetworkInfoRequest{} } func (m *NetworkInfoRequest) String() string { return proto.CompactTextString(m) } func (*NetworkInfoRequest) ProtoMessage() {} func (*NetworkInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{78} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{78} } func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NetworkInfoRequest.Unmarshal(m, b) @@ -5679,7 +5689,7 @@ func (m *NetworkInfo) Reset() { *m = NetworkInfo{} } func (m *NetworkInfo) String() string { return proto.CompactTextString(m) } func (*NetworkInfo) ProtoMessage() {} func (*NetworkInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{79} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{79} } func (m *NetworkInfo) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NetworkInfo.Unmarshal(m, b) @@ -5772,7 +5782,7 @@ func (m *StopRequest) Reset() { *m = StopRequest{} } func (m *StopRequest) String() string { return proto.CompactTextString(m) } func (*StopRequest) ProtoMessage() {} func (*StopRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{80} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{80} } func (m *StopRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StopRequest.Unmarshal(m, b) @@ -5802,7 +5812,7 @@ func (m *StopResponse) Reset() { *m = StopResponse{} } func (m *StopResponse) String() string { return proto.CompactTextString(m) } func (*StopResponse) ProtoMessage() {} func (*StopResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{81} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{81} } func (m *StopResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_StopResponse.Unmarshal(m, b) @@ -5832,7 +5842,7 @@ func (m *GraphTopologySubscription) Reset() { *m = GraphTopologySubscrip func (m *GraphTopologySubscription) String() string { return proto.CompactTextString(m) } func (*GraphTopologySubscription) ProtoMessage() {} func (*GraphTopologySubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{82} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{82} } func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GraphTopologySubscription.Unmarshal(m, b) @@ -5865,7 +5875,7 @@ func (m *GraphTopologyUpdate) Reset() { *m = GraphTopologyUpdate{} } func (m *GraphTopologyUpdate) String() string { return proto.CompactTextString(m) } func (*GraphTopologyUpdate) ProtoMessage() {} func (*GraphTopologyUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{83} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{83} } func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GraphTopologyUpdate.Unmarshal(m, b) @@ -5920,7 +5930,7 @@ func (m *NodeUpdate) Reset() { *m = NodeUpdate{} } func (m *NodeUpdate) String() string { return proto.CompactTextString(m) } func (*NodeUpdate) ProtoMessage() {} func (*NodeUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{84} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{84} } func (m *NodeUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NodeUpdate.Unmarshal(m, b) @@ -5988,7 +5998,7 @@ func (m *ChannelEdgeUpdate) Reset() { *m = ChannelEdgeUpdate{} } func (m *ChannelEdgeUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelEdgeUpdate) ProtoMessage() {} func (*ChannelEdgeUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{85} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{85} } func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEdgeUpdate.Unmarshal(m, b) @@ -6068,7 +6078,7 @@ func (m *ClosedChannelUpdate) Reset() { *m = ClosedChannelUpdate{} } func (m *ClosedChannelUpdate) String() string { return proto.CompactTextString(m) } func (*ClosedChannelUpdate) ProtoMessage() {} func (*ClosedChannelUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{86} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{86} } func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ClosedChannelUpdate.Unmarshal(m, b) @@ -6116,6 +6126,94 @@ func (m *ClosedChannelUpdate) GetChanPoint() *ChannelPoint { return nil } +type HopPeg struct { + // / The public key of the pegged node. + NodeId string `protobuf:"bytes,1,opt,name=node_id,proto3" json:"node_id,omitempty"` + // / Optional. If not 0, the unique identifier of the pegged channel leading to the node. + ChanId uint64 `protobuf:"varint,2,opt,name=chan_id,proto3" json:"chan_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HopPeg) Reset() { *m = HopPeg{} } +func (m *HopPeg) String() string { return proto.CompactTextString(m) } +func (*HopPeg) ProtoMessage() {} +func (*HopPeg) Descriptor() ([]byte, []int) { + return fileDescriptor_rpc_2f0f5e700a80a784, []int{87} +} +func (m *HopPeg) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HopPeg.Unmarshal(m, b) +} +func (m *HopPeg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HopPeg.Marshal(b, m, deterministic) +} +func (dst *HopPeg) XXX_Merge(src proto.Message) { + xxx_messageInfo_HopPeg.Merge(dst, src) +} +func (m *HopPeg) XXX_Size() int { + return xxx_messageInfo_HopPeg.Size(m) +} +func (m *HopPeg) XXX_DiscardUnknown() { + xxx_messageInfo_HopPeg.DiscardUnknown(m) +} + +var xxx_messageInfo_HopPeg proto.InternalMessageInfo + +func (m *HopPeg) GetNodeId() string { + if m != nil { + return m.NodeId + } + return "" +} + +func (m *HopPeg) GetChanId() uint64 { + if m != nil { + return m.ChanId + } + return 0 +} + +type RoutePeg struct { + // * + // A list of hop pegs that that the selected route needs to pass through in that order. + HopPegs []*HopPeg `protobuf:"bytes,1,rep,name=hop_pegs,proto3" json:"hop_pegs,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RoutePeg) Reset() { *m = RoutePeg{} } +func (m *RoutePeg) String() string { return proto.CompactTextString(m) } +func (*RoutePeg) ProtoMessage() {} +func (*RoutePeg) Descriptor() ([]byte, []int) { + return fileDescriptor_rpc_2f0f5e700a80a784, []int{88} +} +func (m *RoutePeg) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_RoutePeg.Unmarshal(m, b) +} +func (m *RoutePeg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_RoutePeg.Marshal(b, m, deterministic) +} +func (dst *RoutePeg) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoutePeg.Merge(dst, src) +} +func (m *RoutePeg) XXX_Size() int { + return xxx_messageInfo_RoutePeg.Size(m) +} +func (m *RoutePeg) XXX_DiscardUnknown() { + xxx_messageInfo_RoutePeg.DiscardUnknown(m) +} + +var xxx_messageInfo_RoutePeg proto.InternalMessageInfo + +func (m *RoutePeg) GetHopPegs() []*HopPeg { + if m != nil { + return m.HopPegs + } + return nil +} + type HopHint struct { // / The public key of the node at the start of the channel. NodeId string `protobuf:"bytes,1,opt,name=node_id,proto3" json:"node_id,omitempty"` @@ -6138,7 +6236,7 @@ func (m *HopHint) Reset() { *m = HopHint{} } func (m *HopHint) String() string { return proto.CompactTextString(m) } func (*HopHint) ProtoMessage() {} func (*HopHint) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{87} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{89} } func (m *HopHint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HopHint.Unmarshal(m, b) @@ -6207,7 +6305,7 @@ func (m *RouteHint) Reset() { *m = RouteHint{} } func (m *RouteHint) String() string { return proto.CompactTextString(m) } func (*RouteHint) ProtoMessage() {} func (*RouteHint) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{88} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{90} } func (m *RouteHint) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RouteHint.Unmarshal(m, b) @@ -6322,7 +6420,7 @@ func (m *Invoice) Reset() { *m = Invoice{} } func (m *Invoice) String() string { return proto.CompactTextString(m) } func (*Invoice) ProtoMessage() {} func (*Invoice) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{89} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{91} } func (m *Invoice) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Invoice.Unmarshal(m, b) @@ -6514,7 +6612,7 @@ func (m *AddInvoiceResponse) Reset() { *m = AddInvoiceResponse{} } func (m *AddInvoiceResponse) String() string { return proto.CompactTextString(m) } func (*AddInvoiceResponse) ProtoMessage() {} func (*AddInvoiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{90} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{92} } func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AddInvoiceResponse.Unmarshal(m, b) @@ -6571,7 +6669,7 @@ func (m *PaymentHash) Reset() { *m = PaymentHash{} } func (m *PaymentHash) String() string { return proto.CompactTextString(m) } func (*PaymentHash) ProtoMessage() {} func (*PaymentHash) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{91} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{93} } func (m *PaymentHash) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PaymentHash.Unmarshal(m, b) @@ -6627,7 +6725,7 @@ func (m *ListInvoiceRequest) Reset() { *m = ListInvoiceRequest{} } func (m *ListInvoiceRequest) String() string { return proto.CompactTextString(m) } func (*ListInvoiceRequest) ProtoMessage() {} func (*ListInvoiceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{92} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{94} } func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListInvoiceRequest.Unmarshal(m, b) @@ -6697,7 +6795,7 @@ func (m *ListInvoiceResponse) Reset() { *m = ListInvoiceResponse{} } func (m *ListInvoiceResponse) String() string { return proto.CompactTextString(m) } func (*ListInvoiceResponse) ProtoMessage() {} func (*ListInvoiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{93} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{95} } func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListInvoiceResponse.Unmarshal(m, b) @@ -6760,7 +6858,7 @@ func (m *InvoiceSubscription) Reset() { *m = InvoiceSubscription{} } func (m *InvoiceSubscription) String() string { return proto.CompactTextString(m) } func (*InvoiceSubscription) ProtoMessage() {} func (*InvoiceSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{94} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{96} } func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_InvoiceSubscription.Unmarshal(m, b) @@ -6820,7 +6918,7 @@ func (m *Payment) Reset() { *m = Payment{} } func (m *Payment) String() string { return proto.CompactTextString(m) } func (*Payment) ProtoMessage() {} func (*Payment) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{95} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{97} } func (m *Payment) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Payment.Unmarshal(m, b) @@ -6907,7 +7005,7 @@ func (m *ListPaymentsRequest) Reset() { *m = ListPaymentsRequest{} } func (m *ListPaymentsRequest) String() string { return proto.CompactTextString(m) } func (*ListPaymentsRequest) ProtoMessage() {} func (*ListPaymentsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{96} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{98} } func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPaymentsRequest.Unmarshal(m, b) @@ -6939,7 +7037,7 @@ func (m *ListPaymentsResponse) Reset() { *m = ListPaymentsResponse{} } func (m *ListPaymentsResponse) String() string { return proto.CompactTextString(m) } func (*ListPaymentsResponse) ProtoMessage() {} func (*ListPaymentsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{97} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{99} } func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPaymentsResponse.Unmarshal(m, b) @@ -6976,7 +7074,7 @@ func (m *DeleteAllPaymentsRequest) Reset() { *m = DeleteAllPaymentsReque func (m *DeleteAllPaymentsRequest) String() string { return proto.CompactTextString(m) } func (*DeleteAllPaymentsRequest) ProtoMessage() {} func (*DeleteAllPaymentsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{98} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{100} } func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DeleteAllPaymentsRequest.Unmarshal(m, b) @@ -7006,7 +7104,7 @@ func (m *DeleteAllPaymentsResponse) Reset() { *m = DeleteAllPaymentsResp func (m *DeleteAllPaymentsResponse) String() string { return proto.CompactTextString(m) } func (*DeleteAllPaymentsResponse) ProtoMessage() {} func (*DeleteAllPaymentsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{99} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{101} } func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DeleteAllPaymentsResponse.Unmarshal(m, b) @@ -7037,7 +7135,7 @@ func (m *AbandonChannelRequest) Reset() { *m = AbandonChannelRequest{} } func (m *AbandonChannelRequest) String() string { return proto.CompactTextString(m) } func (*AbandonChannelRequest) ProtoMessage() {} func (*AbandonChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{100} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{102} } func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AbandonChannelRequest.Unmarshal(m, b) @@ -7074,7 +7172,7 @@ func (m *AbandonChannelResponse) Reset() { *m = AbandonChannelResponse{} func (m *AbandonChannelResponse) String() string { return proto.CompactTextString(m) } func (*AbandonChannelResponse) ProtoMessage() {} func (*AbandonChannelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{101} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{103} } func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AbandonChannelResponse.Unmarshal(m, b) @@ -7106,7 +7204,7 @@ func (m *DebugLevelRequest) Reset() { *m = DebugLevelRequest{} } func (m *DebugLevelRequest) String() string { return proto.CompactTextString(m) } func (*DebugLevelRequest) ProtoMessage() {} func (*DebugLevelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{102} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{104} } func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DebugLevelRequest.Unmarshal(m, b) @@ -7151,7 +7249,7 @@ func (m *DebugLevelResponse) Reset() { *m = DebugLevelResponse{} } func (m *DebugLevelResponse) String() string { return proto.CompactTextString(m) } func (*DebugLevelResponse) ProtoMessage() {} func (*DebugLevelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{103} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{105} } func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DebugLevelResponse.Unmarshal(m, b) @@ -7190,7 +7288,7 @@ func (m *PayReqString) Reset() { *m = PayReqString{} } func (m *PayReqString) String() string { return proto.CompactTextString(m) } func (*PayReqString) ProtoMessage() {} func (*PayReqString) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{104} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{106} } func (m *PayReqString) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PayReqString.Unmarshal(m, b) @@ -7237,7 +7335,7 @@ func (m *PayReq) Reset() { *m = PayReq{} } func (m *PayReq) String() string { return proto.CompactTextString(m) } func (*PayReq) ProtoMessage() {} func (*PayReq) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{105} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{107} } func (m *PayReq) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PayReq.Unmarshal(m, b) @@ -7337,7 +7435,7 @@ func (m *FeeReportRequest) Reset() { *m = FeeReportRequest{} } func (m *FeeReportRequest) String() string { return proto.CompactTextString(m) } func (*FeeReportRequest) ProtoMessage() {} func (*FeeReportRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{106} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{108} } func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeReportRequest.Unmarshal(m, b) @@ -7375,7 +7473,7 @@ func (m *ChannelFeeReport) Reset() { *m = ChannelFeeReport{} } func (m *ChannelFeeReport) String() string { return proto.CompactTextString(m) } func (*ChannelFeeReport) ProtoMessage() {} func (*ChannelFeeReport) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{107} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{109} } func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelFeeReport.Unmarshal(m, b) @@ -7441,7 +7539,7 @@ func (m *FeeReportResponse) Reset() { *m = FeeReportResponse{} } func (m *FeeReportResponse) String() string { return proto.CompactTextString(m) } func (*FeeReportResponse) ProtoMessage() {} func (*FeeReportResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{108} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{110} } func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_FeeReportResponse.Unmarshal(m, b) @@ -7509,7 +7607,7 @@ func (m *PolicyUpdateRequest) Reset() { *m = PolicyUpdateRequest{} } func (m *PolicyUpdateRequest) String() string { return proto.CompactTextString(m) } func (*PolicyUpdateRequest) ProtoMessage() {} func (*PolicyUpdateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{109} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{111} } func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PolicyUpdateRequest.Unmarshal(m, b) @@ -7670,7 +7768,7 @@ func (m *PolicyUpdateResponse) Reset() { *m = PolicyUpdateResponse{} } func (m *PolicyUpdateResponse) String() string { return proto.CompactTextString(m) } func (*PolicyUpdateResponse) ProtoMessage() {} func (*PolicyUpdateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{110} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{112} } func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PolicyUpdateResponse.Unmarshal(m, b) @@ -7708,7 +7806,7 @@ func (m *ForwardingHistoryRequest) Reset() { *m = ForwardingHistoryReque func (m *ForwardingHistoryRequest) String() string { return proto.CompactTextString(m) } func (*ForwardingHistoryRequest) ProtoMessage() {} func (*ForwardingHistoryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{111} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{113} } func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingHistoryRequest.Unmarshal(m, b) @@ -7780,7 +7878,7 @@ func (m *ForwardingEvent) Reset() { *m = ForwardingEvent{} } func (m *ForwardingEvent) String() string { return proto.CompactTextString(m) } func (*ForwardingEvent) ProtoMessage() {} func (*ForwardingEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{112} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{114} } func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingEvent.Unmarshal(m, b) @@ -7863,7 +7961,7 @@ func (m *ForwardingHistoryResponse) Reset() { *m = ForwardingHistoryResp func (m *ForwardingHistoryResponse) String() string { return proto.CompactTextString(m) } func (*ForwardingHistoryResponse) ProtoMessage() {} func (*ForwardingHistoryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_rpc_39d91cdf3094ea9f, []int{113} + return fileDescriptor_rpc_2f0f5e700a80a784, []int{115} } func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ForwardingHistoryResponse.Unmarshal(m, b) @@ -7991,6 +8089,8 @@ func init() { proto.RegisterType((*NodeUpdate)(nil), "lnrpc.NodeUpdate") proto.RegisterType((*ChannelEdgeUpdate)(nil), "lnrpc.ChannelEdgeUpdate") proto.RegisterType((*ClosedChannelUpdate)(nil), "lnrpc.ClosedChannelUpdate") + proto.RegisterType((*HopPeg)(nil), "lnrpc.HopPeg") + proto.RegisterType((*RoutePeg)(nil), "lnrpc.RoutePeg") proto.RegisterType((*HopHint)(nil), "lnrpc.HopHint") proto.RegisterType((*RouteHint)(nil), "lnrpc.RouteHint") proto.RegisterType((*Invoice)(nil), "lnrpc.Invoice") @@ -10363,446 +10463,450 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{ Metadata: "rpc.proto", } -func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_39d91cdf3094ea9f) } - -var fileDescriptor_rpc_39d91cdf3094ea9f = []byte{ - // 7002 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5c, 0x5f, 0x6c, 0x24, 0xc9, - 0x59, 0xdf, 0x9e, 0x3f, 0xf6, 0xcc, 0x37, 0xe3, 0xf1, 0xb8, 0xfc, 0x67, 0x67, 0xe7, 0xf6, 0xf6, - 0xf6, 0x3a, 0xcb, 0xad, 0xe3, 0x1c, 0xeb, 0xbd, 0x4d, 0x72, 0x5c, 0xee, 0x48, 0xc0, 0x6b, 0x7b, - 0xd7, 0x9b, 0xf8, 0xbc, 0x4e, 0x7b, 0x37, 0x4b, 0x2e, 0x41, 0x93, 0xf6, 0x4c, 0x79, 0xdc, 0xb7, - 0x3d, 0xdd, 0x93, 0xee, 0x1e, 0x7b, 0x27, 0xc7, 0x49, 0x08, 0x10, 0x91, 0x10, 0x08, 0x01, 0x2f, - 0x04, 0x05, 0x21, 0x05, 0x24, 0xc8, 0x23, 0x0f, 0x89, 0x90, 0x80, 0x37, 0x84, 0x04, 0x12, 0x42, - 0x90, 0x47, 0x24, 0x5e, 0xe0, 0x25, 0xf0, 0x86, 0xc4, 0x23, 0x12, 0xaa, 0xaf, 0xfe, 0x74, 0x55, - 0x77, 0xcf, 0x7a, 0x2f, 0x09, 0x3c, 0xd9, 0xf5, 0xab, 0xaf, 0xeb, 0xef, 0xf7, 0xaf, 0xbe, 0xfa, - 0x6a, 0xa0, 0x1e, 0x8d, 0xfb, 0xb7, 0xc6, 0x51, 0x98, 0x84, 0xa4, 0xea, 0x07, 0xd1, 0xb8, 0xdf, - 0xbd, 0x3a, 0x0c, 0xc3, 0xa1, 0x4f, 0x37, 0xdd, 0xb1, 0xb7, 0xe9, 0x06, 0x41, 0x98, 0xb8, 0x89, - 0x17, 0x06, 0x31, 0x27, 0xb2, 0xbf, 0x06, 0xad, 0xfb, 0x34, 0x38, 0xa2, 0x74, 0xe0, 0xd0, 0xaf, - 0x4f, 0x68, 0x9c, 0x90, 0x4f, 0xc0, 0x92, 0x4b, 0xbf, 0x41, 0xe9, 0xa0, 0x37, 0x76, 0xe3, 0x78, - 0x7c, 0x1a, 0xb9, 0x31, 0xed, 0x58, 0xd7, 0xad, 0xf5, 0xa6, 0xd3, 0xe6, 0x15, 0x87, 0x0a, 0x27, - 0xaf, 0x42, 0x33, 0x66, 0xa4, 0x34, 0x48, 0xa2, 0x70, 0x3c, 0xed, 0x94, 0x90, 0xae, 0xc1, 0xb0, - 0x5d, 0x0e, 0xd9, 0x3e, 0x2c, 0xaa, 0x1e, 0xe2, 0x71, 0x18, 0xc4, 0x94, 0xdc, 0x86, 0x95, 0xbe, - 0x37, 0x3e, 0xa5, 0x51, 0x0f, 0x3f, 0x1e, 0x05, 0x74, 0x14, 0x06, 0x5e, 0xbf, 0x63, 0x5d, 0x2f, - 0xaf, 0xd7, 0x1d, 0xc2, 0xeb, 0xd8, 0x17, 0xef, 0x8a, 0x1a, 0x72, 0x13, 0x16, 0x69, 0xc0, 0x71, - 0x3a, 0xc0, 0xaf, 0x44, 0x57, 0xad, 0x14, 0x66, 0x1f, 0xd8, 0x7f, 0x63, 0xc1, 0xd2, 0x83, 0xc0, - 0x4b, 0x9e, 0xb8, 0xbe, 0x4f, 0x13, 0x39, 0xa7, 0x9b, 0xb0, 0x78, 0x8e, 0x00, 0xce, 0xe9, 0x3c, - 0x8c, 0x06, 0x62, 0x46, 0x2d, 0x0e, 0x1f, 0x0a, 0x74, 0xe6, 0xc8, 0x4a, 0x33, 0x47, 0x56, 0xb8, - 0x5c, 0xe5, 0x19, 0xcb, 0x75, 0x13, 0x16, 0x23, 0xda, 0x0f, 0xcf, 0x68, 0x34, 0xed, 0x9d, 0x7b, - 0xc1, 0x20, 0x3c, 0xef, 0x54, 0xae, 0x5b, 0xeb, 0x55, 0xa7, 0x25, 0xe1, 0x27, 0x88, 0xda, 0x2b, - 0x40, 0xf4, 0x59, 0xf0, 0x75, 0xb3, 0x87, 0xb0, 0xfc, 0x38, 0xf0, 0xc3, 0xfe, 0xd3, 0x1f, 0x71, - 0x76, 0x05, 0xdd, 0x97, 0x0a, 0xbb, 0x5f, 0x83, 0x15, 0xb3, 0x23, 0x31, 0x00, 0x0a, 0xab, 0xdb, - 0xa7, 0x6e, 0x30, 0xa4, 0xb2, 0x49, 0x39, 0x84, 0x8f, 0x43, 0xbb, 0x3f, 0x89, 0x22, 0x1a, 0xe4, - 0xc6, 0xb0, 0x28, 0x70, 0x35, 0x88, 0x57, 0xa1, 0x19, 0xd0, 0xf3, 0x94, 0x4c, 0xb0, 0x4c, 0x40, - 0xcf, 0x25, 0x89, 0xdd, 0x81, 0xb5, 0x6c, 0x37, 0x62, 0x00, 0x3f, 0xb4, 0xa0, 0xf2, 0x38, 0x79, - 0x16, 0x92, 0x5b, 0x50, 0x49, 0xa6, 0x63, 0xce, 0x98, 0xad, 0x3b, 0xe4, 0x16, 0xf2, 0xfa, 0xad, - 0xad, 0xc1, 0x20, 0xa2, 0x71, 0xfc, 0x68, 0x3a, 0xa6, 0x4e, 0xd3, 0xe5, 0x85, 0x1e, 0xa3, 0x23, - 0x1d, 0x98, 0x17, 0x65, 0xec, 0xb0, 0xee, 0xc8, 0x22, 0xb9, 0x06, 0xe0, 0x8e, 0xc2, 0x49, 0x90, - 0xf4, 0x62, 0x37, 0xc1, 0x9d, 0x2b, 0x3b, 0x1a, 0x42, 0x6e, 0xc0, 0x42, 0xdc, 0x8f, 0xbc, 0x71, - 0xd2, 0x1b, 0x4f, 0x8e, 0x9f, 0xd2, 0x29, 0xee, 0x58, 0xdd, 0x31, 0x41, 0xf2, 0x09, 0xa8, 0x85, - 0x93, 0x64, 0x1c, 0x7a, 0x41, 0xd2, 0xa9, 0x5e, 0xb7, 0xd6, 0x1b, 0x77, 0x16, 0xc5, 0x98, 0x1e, - 0x4e, 0x92, 0x43, 0x06, 0x3b, 0x8a, 0x80, 0x35, 0xd9, 0x0f, 0x83, 0x13, 0x2f, 0x1a, 0x71, 0x59, - 0xec, 0xcc, 0x61, 0xaf, 0x26, 0x68, 0x7f, 0xab, 0x04, 0x8d, 0x47, 0x91, 0x1b, 0xc4, 0x6e, 0x9f, - 0x01, 0x6c, 0x0a, 0xc9, 0xb3, 0xde, 0xa9, 0x1b, 0x9f, 0xe2, 0xac, 0xeb, 0x8e, 0x2c, 0x92, 0x35, - 0x98, 0xe3, 0x03, 0xc6, 0xb9, 0x95, 0x1d, 0x51, 0x22, 0xaf, 0xc3, 0x52, 0x30, 0x19, 0xf5, 0xcc, - 0xbe, 0xca, 0xb8, 0xe3, 0xf9, 0x0a, 0xb6, 0x10, 0xc7, 0x6c, 0xcf, 0x79, 0x17, 0x7c, 0x96, 0x1a, - 0x42, 0x6c, 0x68, 0x8a, 0x12, 0xf5, 0x86, 0xa7, 0x7c, 0x9a, 0x55, 0xc7, 0xc0, 0x58, 0x1b, 0x89, - 0x37, 0xa2, 0xbd, 0x38, 0x71, 0x47, 0x63, 0x31, 0x2d, 0x0d, 0xc1, 0xfa, 0x30, 0x71, 0xfd, 0xde, - 0x09, 0xa5, 0x71, 0x67, 0x5e, 0xd4, 0x2b, 0x84, 0xbc, 0x06, 0xad, 0x01, 0x8d, 0x93, 0x9e, 0xd8, - 0x1c, 0x1a, 0x77, 0x6a, 0x28, 0x79, 0x19, 0x94, 0x71, 0xc8, 0x7d, 0x9a, 0x68, 0xab, 0x13, 0x0b, - 0x4e, 0xb4, 0xf7, 0x81, 0x68, 0xf0, 0x0e, 0x4d, 0x5c, 0xcf, 0x8f, 0xc9, 0x9b, 0xd0, 0x4c, 0x34, - 0x62, 0xd4, 0x34, 0x0d, 0xc5, 0x36, 0xda, 0x07, 0x8e, 0x41, 0x67, 0xdf, 0x87, 0xda, 0x3d, 0x4a, - 0xf7, 0xbd, 0x91, 0x97, 0x90, 0x35, 0xa8, 0x9e, 0x78, 0xcf, 0x28, 0x67, 0xec, 0xf2, 0xde, 0x25, - 0x87, 0x17, 0x49, 0x17, 0xe6, 0xc7, 0x34, 0xea, 0x53, 0xb9, 0xfc, 0x7b, 0x97, 0x1c, 0x09, 0xdc, - 0x9d, 0x87, 0xaa, 0xcf, 0x3e, 0xb6, 0xff, 0xb9, 0x04, 0x8d, 0x23, 0x1a, 0x28, 0x81, 0x21, 0x50, - 0x61, 0x53, 0x12, 0x42, 0x82, 0xff, 0x93, 0x57, 0xa0, 0x81, 0xd3, 0x8c, 0x93, 0xc8, 0x0b, 0x86, - 0x82, 0x4f, 0x81, 0x41, 0x47, 0x88, 0x90, 0x36, 0x94, 0xdd, 0x91, 0xe4, 0x51, 0xf6, 0x2f, 0x13, - 0xa6, 0xb1, 0x3b, 0x1d, 0x31, 0xb9, 0x53, 0xbb, 0xd6, 0x74, 0x1a, 0x02, 0xdb, 0x63, 0xdb, 0x76, - 0x0b, 0x96, 0x75, 0x12, 0xd9, 0x7a, 0x15, 0x5b, 0x5f, 0xd2, 0x28, 0x45, 0x27, 0x37, 0x61, 0x51, - 0xd2, 0x47, 0x7c, 0xb0, 0xb8, 0x8f, 0x75, 0xa7, 0x25, 0x60, 0x39, 0x85, 0x75, 0x68, 0x9f, 0x78, - 0x81, 0xeb, 0xf7, 0xfa, 0x7e, 0x72, 0xd6, 0x1b, 0x50, 0x3f, 0x71, 0x71, 0x47, 0xab, 0x4e, 0x0b, - 0xf1, 0x6d, 0x3f, 0x39, 0xdb, 0x61, 0x28, 0x79, 0x1d, 0xea, 0x27, 0x94, 0xf6, 0x70, 0x25, 0x3a, - 0x35, 0x43, 0x3a, 0xe4, 0xea, 0x3a, 0xb5, 0x13, 0xb9, 0xce, 0xeb, 0xd0, 0x0e, 0x27, 0xc9, 0x30, - 0xf4, 0x82, 0x61, 0xaf, 0x7f, 0xea, 0x06, 0x3d, 0x6f, 0xd0, 0xa9, 0x5f, 0xb7, 0xd6, 0x2b, 0x4e, - 0x4b, 0xe2, 0x4c, 0x3b, 0x3c, 0x18, 0xd8, 0x7f, 0x61, 0x41, 0x93, 0x2f, 0xaa, 0x30, 0x2c, 0x37, - 0x60, 0x41, 0x8e, 0x9d, 0x46, 0x51, 0x18, 0x09, 0x41, 0x31, 0x41, 0xb2, 0x01, 0x6d, 0x09, 0x8c, - 0x23, 0xea, 0x8d, 0xdc, 0x21, 0x15, 0x5a, 0x28, 0x87, 0x93, 0x3b, 0x69, 0x8b, 0x51, 0x38, 0x49, - 0xb8, 0x6a, 0x6f, 0xdc, 0x69, 0x8a, 0xe1, 0x3b, 0x0c, 0x73, 0x4c, 0x12, 0x26, 0x28, 0x05, 0x9b, - 0x62, 0x60, 0xf6, 0xf7, 0x2c, 0x20, 0x6c, 0xe8, 0x8f, 0x42, 0xde, 0x84, 0x58, 0xd3, 0xec, 0x7e, - 0x5a, 0x2f, 0xbc, 0x9f, 0xa5, 0x59, 0xfb, 0xb9, 0x0e, 0x73, 0x38, 0x2c, 0x26, 0xf9, 0xe5, 0xec, - 0xd0, 0xef, 0x96, 0x3a, 0x96, 0x23, 0xea, 0x89, 0x0d, 0x55, 0x3e, 0xc7, 0x4a, 0xc1, 0x1c, 0x79, - 0x95, 0xfd, 0x1d, 0x0b, 0x9a, 0x6c, 0xf5, 0x03, 0xea, 0xa3, 0x56, 0x23, 0xb7, 0x81, 0x9c, 0x4c, - 0x82, 0x01, 0xdb, 0xac, 0xe4, 0x99, 0x37, 0xe8, 0x1d, 0x4f, 0x59, 0x57, 0x38, 0xee, 0xbd, 0x4b, - 0x4e, 0x41, 0x1d, 0x79, 0x1d, 0xda, 0x06, 0x1a, 0x27, 0x11, 0x1f, 0xfd, 0xde, 0x25, 0x27, 0x57, - 0xc3, 0x16, 0x93, 0xe9, 0xcd, 0x49, 0xd2, 0xf3, 0x82, 0x01, 0x7d, 0x86, 0xeb, 0xbf, 0xe0, 0x18, - 0xd8, 0xdd, 0x16, 0x34, 0xf5, 0xef, 0xec, 0xf7, 0xa1, 0x26, 0xb5, 0x2e, 0x6a, 0x9c, 0xcc, 0xb8, - 0x1c, 0x0d, 0x21, 0x5d, 0xa8, 0x99, 0xa3, 0x70, 0x6a, 0x1f, 0xa5, 0x6f, 0xfb, 0x73, 0xd0, 0xde, - 0x67, 0xaa, 0x2f, 0xf0, 0x82, 0xa1, 0x30, 0x3f, 0x4c, 0x1f, 0x0b, 0x5b, 0xc1, 0xf9, 0x4f, 0x94, - 0x98, 0xd0, 0x9f, 0x86, 0x71, 0x22, 0xfa, 0xc1, 0xff, 0xed, 0x7f, 0xb3, 0x60, 0x91, 0x31, 0xc2, - 0xbb, 0x6e, 0x30, 0x95, 0x5c, 0xb0, 0x0f, 0x4d, 0xd6, 0xd4, 0xa3, 0x70, 0x8b, 0x6b, 0x75, 0xae, - 0xad, 0xd6, 0xc5, 0x7e, 0x64, 0xa8, 0x6f, 0xe9, 0xa4, 0xcc, 0xe9, 0x9a, 0x3a, 0xc6, 0xd7, 0x4c, - 0xad, 0x24, 0x6e, 0x34, 0xa4, 0x09, 0xea, 0x7b, 0xa1, 0xff, 0x81, 0x43, 0xdb, 0x61, 0x70, 0x42, - 0xae, 0x43, 0x33, 0x76, 0x93, 0xde, 0x98, 0x46, 0xb8, 0x26, 0xa8, 0x1a, 0xca, 0x0e, 0xc4, 0x6e, - 0x72, 0x48, 0xa3, 0xbb, 0xd3, 0x84, 0x76, 0x7f, 0x0e, 0x96, 0x72, 0xbd, 0x30, 0x6d, 0x94, 0x4e, - 0x91, 0xfd, 0x4b, 0x56, 0xa0, 0x7a, 0xe6, 0xfa, 0x13, 0x2a, 0xcc, 0x10, 0x2f, 0xbc, 0x5d, 0x7a, - 0xcb, 0xb2, 0x5f, 0x83, 0x76, 0x3a, 0x6c, 0x21, 0xac, 0x04, 0x2a, 0x6c, 0xa5, 0x45, 0x03, 0xf8, - 0xbf, 0xfd, 0x6d, 0x8b, 0x13, 0x6e, 0x87, 0x9e, 0x52, 0xe9, 0x8c, 0x90, 0x69, 0x7e, 0x49, 0xc8, - 0xfe, 0x9f, 0x69, 0xf2, 0x7e, 0xfc, 0xc9, 0x92, 0x2b, 0x50, 0x8b, 0x69, 0x30, 0xe8, 0xb9, 0xbe, - 0x8f, 0x9a, 0xaf, 0xe6, 0xcc, 0xb3, 0xf2, 0x96, 0xef, 0xdb, 0x37, 0x61, 0x49, 0x1b, 0xdd, 0x73, - 0xe6, 0x71, 0x00, 0x64, 0xdf, 0x8b, 0x93, 0xc7, 0x41, 0x3c, 0xd6, 0x34, 0xe6, 0x4b, 0x50, 0x1f, - 0x79, 0x01, 0x8e, 0x8c, 0xb3, 0x62, 0xd5, 0xa9, 0x8d, 0xbc, 0x80, 0x8d, 0x2b, 0xc6, 0x4a, 0xf7, - 0x99, 0xa8, 0x2c, 0x89, 0x4a, 0xf7, 0x19, 0x56, 0xda, 0x6f, 0xc1, 0xb2, 0xd1, 0x9e, 0xe8, 0xfa, - 0x55, 0xa8, 0x4e, 0x92, 0x67, 0xa1, 0xb4, 0x67, 0x0d, 0xc1, 0x21, 0xcc, 0x43, 0x72, 0x78, 0x8d, - 0xfd, 0x0e, 0x2c, 0x1d, 0xd0, 0x73, 0xc1, 0x99, 0x72, 0x20, 0xaf, 0x5d, 0xe8, 0x3d, 0x61, 0xbd, - 0x7d, 0x0b, 0x88, 0xfe, 0xb1, 0xe8, 0x55, 0xf3, 0xa5, 0x2c, 0xc3, 0x97, 0xb2, 0x5f, 0x03, 0x72, - 0xe4, 0x0d, 0x83, 0x77, 0x69, 0x1c, 0xbb, 0x43, 0xa5, 0xd4, 0xda, 0x50, 0x1e, 0xc5, 0x43, 0x21, - 0x7b, 0xec, 0x5f, 0xfb, 0x93, 0xb0, 0x6c, 0xd0, 0x89, 0x86, 0xaf, 0x42, 0x3d, 0xf6, 0x86, 0x81, - 0x9b, 0x4c, 0x22, 0x2a, 0x9a, 0x4e, 0x01, 0xfb, 0x1e, 0xac, 0x7c, 0x89, 0x46, 0xde, 0xc9, 0xf4, - 0xa2, 0xe6, 0xcd, 0x76, 0x4a, 0xd9, 0x76, 0x76, 0x61, 0x35, 0xd3, 0x8e, 0xe8, 0x9e, 0xb3, 0xaf, - 0xd8, 0xc9, 0x9a, 0xc3, 0x0b, 0x9a, 0x30, 0x97, 0x74, 0x61, 0xb6, 0x1f, 0x03, 0xd9, 0x0e, 0x83, - 0x80, 0xf6, 0x93, 0x43, 0x4a, 0xa3, 0xf4, 0xf4, 0x94, 0xf2, 0x6a, 0xe3, 0xce, 0x65, 0xb1, 0xb2, - 0x59, 0x0d, 0x21, 0x98, 0x98, 0x40, 0x65, 0x4c, 0xa3, 0x11, 0x36, 0x5c, 0x73, 0xf0, 0x7f, 0x7b, - 0x15, 0x96, 0x8d, 0x66, 0x85, 0xe3, 0xfb, 0x06, 0xac, 0xee, 0x78, 0x71, 0x3f, 0xdf, 0x61, 0x07, - 0xe6, 0xc7, 0x93, 0xe3, 0x5e, 0x2a, 0x89, 0xb2, 0xc8, 0x7c, 0xa4, 0xec, 0x27, 0xa2, 0xb1, 0x5f, - 0xb7, 0xa0, 0xb2, 0xf7, 0x68, 0x7f, 0x9b, 0x29, 0x3f, 0x2f, 0xe8, 0x87, 0x23, 0x66, 0x40, 0xf8, - 0xa4, 0x55, 0x79, 0xa6, 0x84, 0x5d, 0x85, 0x3a, 0xda, 0x1d, 0xe6, 0xf6, 0x89, 0x83, 0x4e, 0x0a, - 0x30, 0x97, 0x93, 0x3e, 0x1b, 0x7b, 0x11, 0xfa, 0x94, 0xd2, 0x53, 0xac, 0xa0, 0xde, 0xcc, 0x57, - 0xd8, 0xdf, 0xae, 0xc2, 0xbc, 0xb0, 0x26, 0xd8, 0x5f, 0x3f, 0xf1, 0xce, 0xa8, 0x18, 0x89, 0x28, - 0x31, 0x9b, 0x1e, 0xd1, 0x51, 0x98, 0xd0, 0x9e, 0xb1, 0x0d, 0x26, 0x88, 0x2e, 0x35, 0x6f, 0xa8, - 0xc7, 0x9d, 0xf0, 0x32, 0xa7, 0x32, 0x40, 0xb6, 0x58, 0xd2, 0xa3, 0xa8, 0xa0, 0x47, 0x21, 0x8b, - 0x6c, 0x25, 0xfa, 0xee, 0xd8, 0xed, 0x7b, 0xc9, 0x54, 0xa8, 0x04, 0x55, 0x66, 0x6d, 0xfb, 0x61, - 0xdf, 0xf5, 0x7b, 0xc7, 0xae, 0xef, 0x06, 0x7d, 0x2a, 0xdd, 0x75, 0x03, 0x64, 0xae, 0xab, 0x18, - 0x92, 0x24, 0xe3, 0xee, 0x6d, 0x06, 0x65, 0x06, 0xa9, 0x1f, 0x8e, 0x46, 0x5e, 0xc2, 0x3c, 0x5e, - 0xf4, 0x86, 0xca, 0x8e, 0x86, 0xf0, 0xc3, 0x01, 0x96, 0xce, 0xf9, 0xea, 0xd5, 0xe5, 0xe1, 0x40, - 0x03, 0x59, 0x2b, 0xcc, 0xa5, 0x62, 0x6a, 0xec, 0xe9, 0x79, 0x07, 0x78, 0x2b, 0x29, 0xc2, 0xf6, - 0x61, 0x12, 0xc4, 0x34, 0x49, 0x7c, 0x3a, 0x50, 0x03, 0x6a, 0x20, 0x59, 0xbe, 0x82, 0xdc, 0x86, - 0x65, 0xee, 0x84, 0xc7, 0x6e, 0x12, 0xc6, 0xa7, 0x5e, 0xdc, 0x8b, 0x99, 0x3b, 0xdb, 0x44, 0xfa, - 0xa2, 0x2a, 0xf2, 0x16, 0x5c, 0xce, 0xc0, 0x11, 0xed, 0x53, 0xef, 0x8c, 0x0e, 0x3a, 0x0b, 0xf8, - 0xd5, 0xac, 0x6a, 0x72, 0x1d, 0x1a, 0xec, 0xec, 0x31, 0x19, 0x0f, 0x5c, 0x66, 0x91, 0x5b, 0xb8, - 0x0f, 0x3a, 0x44, 0xde, 0x80, 0x85, 0x31, 0xe5, 0xe6, 0xfc, 0x34, 0xf1, 0xfb, 0x71, 0x67, 0xd1, - 0xd0, 0x6e, 0x8c, 0x73, 0x1d, 0x93, 0x82, 0x31, 0x65, 0x3f, 0x46, 0x27, 0xd4, 0x9d, 0x76, 0xda, - 0xc8, 0x6e, 0x29, 0x80, 0x32, 0x12, 0x79, 0x67, 0x6e, 0x42, 0x3b, 0x4b, 0x5c, 0xa1, 0x8b, 0x22, - 0xfb, 0xce, 0x0b, 0xbc, 0xc4, 0x73, 0x93, 0x30, 0xea, 0x10, 0xac, 0x4b, 0x01, 0xfb, 0x8f, 0x2c, - 0xae, 0x76, 0x05, 0x8b, 0x2a, 0xf5, 0xf9, 0x0a, 0x34, 0x38, 0x73, 0xf6, 0xc2, 0xc0, 0x9f, 0x0a, - 0x7e, 0x05, 0x0e, 0x3d, 0x0c, 0xfc, 0x29, 0xf9, 0x18, 0x2c, 0x78, 0x81, 0x4e, 0xc2, 0x25, 0xbc, - 0x29, 0x41, 0x24, 0x7a, 0x05, 0x1a, 0xe3, 0xc9, 0xb1, 0xef, 0xf5, 0x39, 0x49, 0x99, 0xb7, 0xc2, - 0x21, 0x24, 0x60, 0xce, 0x20, 0x1f, 0x27, 0xa7, 0xa8, 0x20, 0x45, 0x43, 0x60, 0x8c, 0xc4, 0xbe, - 0x0b, 0x2b, 0xe6, 0x00, 0x85, 0x2a, 0xdb, 0x80, 0x9a, 0xe0, 0xfc, 0xb8, 0xd3, 0xc0, 0xd5, 0x6b, - 0x89, 0xd5, 0x13, 0xa4, 0x8e, 0xaa, 0xb7, 0xbf, 0x5f, 0x81, 0x65, 0x81, 0x6e, 0xfb, 0x61, 0x4c, - 0x8f, 0x26, 0xa3, 0x91, 0x1b, 0x15, 0x88, 0x94, 0x75, 0x81, 0x48, 0x95, 0x4c, 0x91, 0x62, 0x8c, - 0x7e, 0xea, 0x7a, 0x01, 0xf7, 0x64, 0xb9, 0x3c, 0x6a, 0x08, 0x59, 0x87, 0xc5, 0xbe, 0x1f, 0xc6, - 0xdc, 0x6b, 0xd3, 0x0f, 0x9d, 0x59, 0x38, 0xaf, 0x02, 0xaa, 0x45, 0x2a, 0x40, 0x17, 0xe1, 0xb9, - 0x8c, 0x08, 0xdb, 0xd0, 0x64, 0x8d, 0x52, 0xa9, 0x91, 0xe6, 0xb9, 0x27, 0xa7, 0x63, 0x6c, 0x3c, - 0x59, 0x81, 0xe1, 0xd2, 0xb9, 0x58, 0x24, 0x2e, 0xec, 0x4c, 0xcb, 0x34, 0x9e, 0x46, 0x5d, 0x17, - 0xe2, 0x92, 0xaf, 0x22, 0xf7, 0x00, 0x78, 0x5f, 0x68, 0x76, 0x01, 0xcd, 0xee, 0x6b, 0xe6, 0x8e, - 0xe8, 0x6b, 0x7f, 0x8b, 0x15, 0x26, 0x11, 0x45, 0x53, 0xac, 0x7d, 0x69, 0xff, 0x86, 0x05, 0x0d, - 0xad, 0x8e, 0xac, 0xc2, 0xd2, 0xf6, 0xc3, 0x87, 0x87, 0xbb, 0xce, 0xd6, 0xa3, 0x07, 0x5f, 0xda, - 0xed, 0x6d, 0xef, 0x3f, 0x3c, 0xda, 0x6d, 0x5f, 0x62, 0xf0, 0xfe, 0xc3, 0xed, 0xad, 0xfd, 0xde, - 0xbd, 0x87, 0xce, 0xb6, 0x84, 0x2d, 0xb2, 0x06, 0xc4, 0xd9, 0x7d, 0xf7, 0xe1, 0xa3, 0x5d, 0x03, - 0x2f, 0x91, 0x36, 0x34, 0xef, 0x3a, 0xbb, 0x5b, 0xdb, 0x7b, 0x02, 0x29, 0x93, 0x15, 0x68, 0xdf, - 0x7b, 0x7c, 0xb0, 0xf3, 0xe0, 0xe0, 0x7e, 0x6f, 0x7b, 0xeb, 0x60, 0x7b, 0x77, 0x7f, 0x77, 0xa7, - 0x5d, 0x21, 0x0b, 0x50, 0xdf, 0xba, 0xbb, 0x75, 0xb0, 0xf3, 0xf0, 0x60, 0x77, 0xa7, 0x5d, 0xb5, - 0xff, 0xd5, 0x82, 0x55, 0x1c, 0xf5, 0x20, 0x2b, 0x20, 0xd7, 0xa1, 0xd1, 0x0f, 0xc3, 0x31, 0x65, - 0xda, 0x5e, 0x29, 0x74, 0x1d, 0x62, 0xcc, 0xcf, 0xd5, 0xe7, 0x49, 0x18, 0xf5, 0xa9, 0x90, 0x0f, - 0x40, 0xe8, 0x1e, 0x43, 0x18, 0xf3, 0x8b, 0xed, 0xe5, 0x14, 0x5c, 0x3c, 0x1a, 0x1c, 0xe3, 0x24, - 0x6b, 0x30, 0x77, 0x1c, 0x51, 0xb7, 0x7f, 0x2a, 0x24, 0x43, 0x94, 0xc8, 0xc7, 0xd3, 0x03, 0x46, - 0x9f, 0xad, 0xbe, 0x4f, 0x07, 0xc8, 0x31, 0x35, 0x67, 0x51, 0xe0, 0xdb, 0x02, 0x66, 0xf2, 0xef, - 0x1e, 0xbb, 0xc1, 0x20, 0x0c, 0xe8, 0x40, 0x38, 0x7b, 0x29, 0x60, 0x1f, 0xc2, 0x5a, 0x76, 0x7e, - 0x42, 0xbe, 0xde, 0xd4, 0xe4, 0x8b, 0xfb, 0x5e, 0xdd, 0xd9, 0xbb, 0xa9, 0xc9, 0xda, 0x7f, 0x58, - 0x50, 0x61, 0xa6, 0x78, 0xb6, 0xd9, 0xd6, 0xbd, 0xab, 0x72, 0x2e, 0x52, 0x85, 0x67, 0x16, 0xae, - 0x9c, 0xb9, 0x01, 0xd3, 0x90, 0xb4, 0x3e, 0xa2, 0xfd, 0x33, 0x9c, 0xb1, 0xaa, 0x67, 0x08, 0x13, - 0x10, 0xe6, 0xfa, 0xe2, 0xd7, 0x42, 0x40, 0x64, 0x59, 0xd6, 0xe1, 0x97, 0xf3, 0x69, 0x1d, 0x7e, - 0xd7, 0x81, 0x79, 0x2f, 0x38, 0x0e, 0x27, 0xc1, 0x00, 0x05, 0xa2, 0xe6, 0xc8, 0x22, 0x5b, 0xbe, - 0x31, 0x0a, 0xaa, 0x37, 0x92, 0xec, 0x9f, 0x02, 0x36, 0x61, 0x47, 0xa3, 0x18, 0x5d, 0x0f, 0x15, - 0x9e, 0x79, 0x13, 0x96, 0x34, 0x2c, 0x75, 0x63, 0xc7, 0x0c, 0xc8, 0xb8, 0xb1, 0xe8, 0xb3, 0xf0, - 0x1a, 0xbb, 0x0d, 0xad, 0xfb, 0x34, 0x79, 0x10, 0x9c, 0x84, 0xb2, 0xa5, 0x3f, 0xad, 0xc0, 0xa2, - 0x82, 0x44, 0x43, 0xeb, 0xb0, 0xe8, 0x0d, 0x68, 0x90, 0x78, 0xc9, 0xb4, 0x67, 0x9c, 0xc0, 0xb2, - 0x30, 0xf3, 0xf5, 0x5c, 0xdf, 0x73, 0x65, 0x34, 0x90, 0x17, 0xc8, 0x1d, 0x58, 0x61, 0x86, 0x48, - 0xda, 0x16, 0xb5, 0xc5, 0xfc, 0xe0, 0x57, 0x58, 0xc7, 0x94, 0x01, 0xc3, 0x85, 0xb6, 0x57, 0x9f, - 0x70, 0x9f, 0xa7, 0xa8, 0x8a, 0xad, 0x1a, 0x6f, 0x89, 0x4d, 0xb9, 0xca, 0x8d, 0x95, 0x02, 0x72, - 0x61, 0xb6, 0x39, 0xae, 0xaa, 0xb2, 0x61, 0x36, 0x2d, 0x54, 0x57, 0xcb, 0x85, 0xea, 0x98, 0x2a, - 0x9b, 0x06, 0x7d, 0x3a, 0xe8, 0x25, 0x61, 0x0f, 0x55, 0x2e, 0xee, 0x4e, 0xcd, 0xc9, 0xc2, 0xe4, - 0x2a, 0xcc, 0x27, 0x34, 0x4e, 0x02, 0x9a, 0xa0, 0x56, 0xaa, 0x61, 0x40, 0x40, 0x42, 0xcc, 0x41, - 0x9d, 0x44, 0x5e, 0xdc, 0x69, 0x62, 0x10, 0x0e, 0xff, 0x27, 0x9f, 0x82, 0xd5, 0x63, 0x1a, 0x27, - 0xbd, 0x53, 0xea, 0x0e, 0x68, 0x84, 0x3b, 0xcd, 0xa3, 0x7d, 0xdc, 0xee, 0x17, 0x57, 0x32, 0x1e, - 0x3a, 0xa3, 0x51, 0xec, 0x85, 0x01, 0x5a, 0xfc, 0xba, 0x23, 0x8b, 0xac, 0x3d, 0x36, 0x79, 0x65, - 0x2f, 0xd5, 0x0a, 0x2e, 0xe2, 0xc4, 0x8b, 0x2b, 0xc9, 0x0d, 0x98, 0xc3, 0x09, 0xc4, 0x9d, 0xb6, - 0x11, 0xd5, 0xd8, 0x66, 0xa0, 0x23, 0xea, 0x3e, 0x5f, 0xa9, 0x35, 0xda, 0x4d, 0xfb, 0x67, 0xa0, - 0x8a, 0x30, 0xdb, 0x74, 0xbe, 0x18, 0x9c, 0x29, 0x78, 0x81, 0x0d, 0x2d, 0xa0, 0xc9, 0x79, 0x18, - 0x3d, 0x95, 0xa1, 0x61, 0x51, 0xb4, 0xbf, 0x81, 0x2e, 0xbe, 0x0a, 0x91, 0x3e, 0x46, 0xff, 0x84, - 0x1d, 0xd4, 0xf8, 0x52, 0xc7, 0xa7, 0xae, 0x38, 0x75, 0xd4, 0x10, 0x38, 0x3a, 0x75, 0x99, 0xda, - 0x32, 0x76, 0x8f, 0x1f, 0xe4, 0x1a, 0x88, 0xed, 0xf1, 0xcd, 0xbb, 0x01, 0x2d, 0x19, 0x7c, 0x8d, - 0x7b, 0x3e, 0x3d, 0x49, 0x64, 0x5c, 0x21, 0x98, 0x8c, 0xf0, 0xb4, 0xb7, 0x4f, 0x4f, 0x12, 0xfb, - 0x00, 0x96, 0x84, 0x2a, 0x79, 0x38, 0xa6, 0xb2, 0xeb, 0xcf, 0x14, 0x99, 0xe4, 0xc6, 0x9d, 0x65, - 0x53, 0xf7, 0xf0, 0x70, 0xb3, 0x49, 0x69, 0x3b, 0x40, 0x74, 0xd5, 0x24, 0x1a, 0x14, 0x76, 0x51, - 0x46, 0x4e, 0xc4, 0x74, 0x0c, 0x8c, 0xad, 0x4f, 0x3c, 0xe9, 0xf7, 0x65, 0xe8, 0x9c, 0x1d, 0x87, - 0x79, 0xd1, 0xfe, 0x33, 0x0b, 0x96, 0xb1, 0x35, 0xe9, 0x54, 0x08, 0xf5, 0xff, 0xd6, 0x47, 0x18, - 0x66, 0xb3, 0xaf, 0x47, 0x93, 0x56, 0xa0, 0xaa, 0x1b, 0x04, 0x5e, 0xf8, 0xe8, 0x87, 0xfa, 0x4a, - 0xf6, 0x50, 0x6f, 0xff, 0xbe, 0x05, 0x4b, 0x5c, 0x27, 0x27, 0x6e, 0x32, 0x89, 0xc5, 0xf4, 0x7f, - 0x16, 0x16, 0xb8, 0x71, 0x15, 0x52, 0x2d, 0x06, 0xba, 0xa2, 0x14, 0x10, 0xa2, 0x9c, 0x78, 0xef, - 0x92, 0x63, 0x12, 0x93, 0x77, 0xd0, 0xc1, 0x09, 0x7a, 0x88, 0x8a, 0xc0, 0xe0, 0x95, 0x02, 0x33, - 0xa0, 0xbe, 0xd7, 0xc8, 0xef, 0xd6, 0x60, 0x8e, 0xfb, 0xbb, 0xf6, 0x7d, 0x58, 0x30, 0x3a, 0x32, - 0x02, 0x0a, 0x4d, 0x1e, 0x50, 0xc8, 0x85, 0xa2, 0x4a, 0x05, 0xa1, 0xa8, 0x3f, 0x2f, 0x03, 0x61, - 0xcc, 0x92, 0xd9, 0x0d, 0xe6, 0x70, 0x87, 0x03, 0xe3, 0xf8, 0xd4, 0x74, 0x74, 0x88, 0xdc, 0x02, - 0xa2, 0x15, 0x65, 0x44, 0x91, 0x5b, 0x9f, 0x82, 0x1a, 0xa6, 0x26, 0x85, 0xf1, 0x16, 0x66, 0x56, - 0x1c, 0x14, 0xf9, 0xb2, 0x17, 0xd6, 0x31, 0x03, 0x33, 0x9e, 0xc4, 0xa7, 0x78, 0xc9, 0x22, 0x0e, - 0x58, 0xb2, 0x9c, 0xdd, 0xdf, 0xb9, 0x0b, 0xf7, 0x77, 0x3e, 0x17, 0xb4, 0xd1, 0x5c, 0xfc, 0x9a, - 0xe9, 0xe2, 0xdf, 0x80, 0x85, 0x11, 0x73, 0x39, 0x13, 0xbf, 0xdf, 0x1b, 0xb1, 0xde, 0xc5, 0x79, - 0xca, 0x00, 0xc9, 0x06, 0xb4, 0x85, 0xbb, 0x91, 0x9e, 0x23, 0x00, 0xd7, 0x38, 0x87, 0x33, 0xfd, - 0x9d, 0x86, 0x71, 0x1a, 0x38, 0xd8, 0x14, 0x60, 0x27, 0xaf, 0x98, 0x71, 0x48, 0x6f, 0x12, 0x88, - 0xfb, 0x15, 0x3a, 0xc0, 0x93, 0x54, 0xcd, 0xc9, 0x57, 0xd8, 0xbf, 0x6b, 0x41, 0x9b, 0xed, 0x99, - 0xc1, 0x96, 0x6f, 0x03, 0x4a, 0xc5, 0x0b, 0x72, 0xa5, 0x41, 0x4b, 0xde, 0x82, 0x3a, 0x96, 0xc3, - 0x31, 0x0d, 0x04, 0x4f, 0x76, 0x4c, 0x9e, 0x4c, 0xf5, 0xc9, 0xde, 0x25, 0x27, 0x25, 0xd6, 0x38, - 0xf2, 0x1f, 0x2d, 0x68, 0x88, 0x5e, 0x7e, 0xe4, 0x30, 0x41, 0x57, 0xbb, 0x10, 0xe3, 0x9c, 0x94, - 0xde, 0x7f, 0xad, 0xc3, 0xe2, 0xc8, 0x4d, 0x26, 0x11, 0xb3, 0xc7, 0x46, 0x88, 0x20, 0x0b, 0x33, - 0xe3, 0x8a, 0xaa, 0x33, 0xee, 0x25, 0x9e, 0xdf, 0x93, 0xb5, 0xe2, 0xea, 0xa9, 0xa8, 0x8a, 0x69, - 0x90, 0x38, 0x71, 0x87, 0x54, 0xd8, 0x4d, 0x5e, 0xb0, 0x3b, 0xb0, 0x26, 0x26, 0x94, 0x71, 0x55, - 0xed, 0xbf, 0x6e, 0xc2, 0xe5, 0x5c, 0x95, 0xba, 0xa7, 0x16, 0x67, 0x5f, 0xdf, 0x1b, 0x1d, 0x87, - 0xca, 0xcf, 0xb7, 0xf4, 0x63, 0xb1, 0x51, 0x45, 0x86, 0xb0, 0x2a, 0x1d, 0x04, 0xb6, 0xa6, 0xa9, - 0x31, 0x2b, 0xa1, 0x95, 0x7a, 0xc3, 0xdc, 0xc2, 0x6c, 0x87, 0x12, 0xd7, 0x85, 0xb8, 0xb8, 0x3d, - 0x72, 0x0a, 0x1d, 0xe5, 0x89, 0x08, 0x65, 0xad, 0x79, 0x2b, 0xac, 0xaf, 0xd7, 0x2f, 0xe8, 0xcb, - 0xf0, 0x6c, 0x9d, 0x99, 0xad, 0x91, 0x29, 0x5c, 0x93, 0x75, 0xa8, 0x8d, 0xf3, 0xfd, 0x55, 0x5e, - 0x68, 0x6e, 0xe8, 0xb3, 0x9b, 0x9d, 0x5e, 0xd0, 0x30, 0x79, 0x1f, 0xd6, 0xce, 0x5d, 0x2f, 0x91, - 0xc3, 0xd2, 0x7c, 0x83, 0x2a, 0x76, 0x79, 0xe7, 0x82, 0x2e, 0x9f, 0xf0, 0x8f, 0x0d, 0x13, 0x35, - 0xa3, 0xc5, 0xee, 0xdf, 0x5b, 0xd0, 0x32, 0xdb, 0x61, 0x6c, 0x2a, 0x64, 0x5f, 0xea, 0x40, 0xe9, - 0x4d, 0x66, 0xe0, 0xfc, 0x51, 0xb9, 0x54, 0x74, 0x54, 0xd6, 0x0f, 0xa8, 0xe5, 0x8b, 0x62, 0x4c, - 0x95, 0x17, 0x8b, 0x31, 0x55, 0x8b, 0x62, 0x4c, 0xdd, 0xff, 0xb6, 0x80, 0xe4, 0x79, 0x89, 0xdc, - 0xe7, 0x67, 0xf5, 0x80, 0xfa, 0x42, 0xa5, 0xfc, 0xf4, 0x8b, 0xf1, 0xa3, 0x5c, 0x3b, 0xf9, 0x35, - 0x13, 0x0c, 0xfd, 0xee, 0x58, 0x77, 0x76, 0x16, 0x9c, 0xa2, 0xaa, 0x4c, 0xd4, 0xab, 0x72, 0x71, - 0xd4, 0xab, 0x7a, 0x71, 0xd4, 0x6b, 0x2e, 0x1b, 0xf5, 0xea, 0xfe, 0x9a, 0x05, 0xcb, 0x05, 0x9b, - 0xfe, 0x93, 0x9b, 0x38, 0xdb, 0x26, 0x43, 0x17, 0x94, 0xc4, 0x36, 0xe9, 0x60, 0xf7, 0x97, 0x60, - 0xc1, 0x60, 0xf4, 0x9f, 0x5c, 0xff, 0x59, 0x7f, 0x8d, 0xf3, 0x99, 0x81, 0x75, 0xff, 0xb3, 0x04, - 0x24, 0x2f, 0x6c, 0xff, 0xaf, 0x63, 0xc8, 0xaf, 0x53, 0xb9, 0x60, 0x9d, 0xfe, 0x4f, 0xed, 0xc0, - 0xeb, 0xb0, 0x24, 0x92, 0x5a, 0xb4, 0x08, 0x0d, 0xe7, 0x98, 0x7c, 0x05, 0xf3, 0x58, 0xcd, 0x90, - 0x63, 0xcd, 0x48, 0x10, 0xd0, 0x8c, 0x61, 0x26, 0xf2, 0x68, 0x77, 0xa1, 0x23, 0x56, 0x68, 0xf7, - 0x8c, 0x06, 0xc9, 0xd1, 0xe4, 0x98, 0x27, 0x86, 0x78, 0x61, 0x60, 0x7f, 0xaf, 0xac, 0x9c, 0x6e, - 0xac, 0x14, 0xe6, 0xfd, 0x53, 0xd0, 0xd4, 0x95, 0xb9, 0xd8, 0x8e, 0x4c, 0x80, 0x8e, 0x19, 0x76, - 0x9d, 0x8a, 0xec, 0x40, 0x0b, 0x55, 0xd6, 0x40, 0x7d, 0x57, 0xc2, 0xef, 0x9e, 0x13, 0x78, 0xd8, - 0xbb, 0xe4, 0x64, 0xbe, 0x21, 0x9f, 0x85, 0x96, 0x79, 0x94, 0x12, 0x3e, 0x42, 0x91, 0x6f, 0xce, - 0x3e, 0x37, 0x89, 0xc9, 0x16, 0xb4, 0xb3, 0x67, 0x31, 0x71, 0x5b, 0x3c, 0xa3, 0x81, 0x1c, 0x39, - 0x79, 0x4b, 0xdc, 0x3d, 0x55, 0x31, 0x08, 0x76, 0xc3, 0xfc, 0x4c, 0x5b, 0xa6, 0x5b, 0xfc, 0x8f, - 0x76, 0x1b, 0xf5, 0x55, 0x80, 0x14, 0x23, 0x6d, 0x68, 0x3e, 0x3c, 0xdc, 0x3d, 0xe8, 0x6d, 0xef, - 0x6d, 0x1d, 0x1c, 0xec, 0xee, 0xb7, 0x2f, 0x11, 0x02, 0x2d, 0x8c, 0x5f, 0xed, 0x28, 0xcc, 0x62, - 0xd8, 0xd6, 0x36, 0x8f, 0x8d, 0x09, 0xac, 0x44, 0x56, 0xa0, 0xfd, 0xe0, 0x20, 0x83, 0x96, 0xef, - 0xd6, 0x95, 0x7c, 0xd8, 0x6b, 0xb0, 0xc2, 0x13, 0x9f, 0xee, 0x72, 0xf6, 0x90, 0xbe, 0xc2, 0x1f, - 0x5a, 0xb0, 0x9a, 0xa9, 0x48, 0x13, 0x0f, 0xb8, 0x3b, 0x60, 0xfa, 0x08, 0x26, 0xc8, 0x78, 0x52, - 0x79, 0x7e, 0x19, 0x0d, 0x92, 0xaf, 0x60, 0x3c, 0xaf, 0x79, 0x8a, 0x19, 0x49, 0x2a, 0xaa, 0xb2, - 0x2f, 0xf3, 0xf4, 0xac, 0x80, 0xfa, 0x99, 0x81, 0x9f, 0xf0, 0x84, 0x2a, 0xbd, 0x22, 0xbd, 0xcb, - 0x33, 0x87, 0x2c, 0x8b, 0xcc, 0xc9, 0x37, 0x5c, 0x0f, 0x73, 0xbc, 0x85, 0x75, 0xf6, 0xf7, 0x2d, - 0x20, 0x5f, 0x9c, 0xd0, 0x68, 0x8a, 0x39, 0x03, 0x2a, 0x1c, 0x78, 0x39, 0x1b, 0xec, 0x9a, 0x1b, - 0x4f, 0x8e, 0xbf, 0x40, 0xa7, 0x32, 0xa1, 0xa5, 0x94, 0x26, 0xb4, 0xbc, 0x0c, 0xc0, 0x0e, 0xc7, - 0x2a, 0x63, 0x01, 0x9d, 0xeb, 0x60, 0x32, 0xe2, 0x0d, 0x16, 0xe6, 0x9c, 0x54, 0x2e, 0xce, 0x39, - 0xa9, 0x5e, 0x90, 0x73, 0x62, 0xbf, 0x03, 0xcb, 0xc6, 0xb8, 0xd5, 0xb6, 0xca, 0xdc, 0x09, 0x2b, - 0x9f, 0x3b, 0x21, 0xf3, 0x26, 0xec, 0x6f, 0x96, 0xa0, 0xbc, 0x17, 0x8e, 0xf5, 0x50, 0xb8, 0x65, - 0x86, 0xc2, 0x85, 0x7f, 0xd0, 0x53, 0xe6, 0x5f, 0x98, 0x0d, 0x03, 0x24, 0x1b, 0xd0, 0x72, 0x47, - 0x49, 0x2f, 0x09, 0x99, 0x3f, 0x74, 0xee, 0x46, 0x03, 0xbe, 0xd7, 0x18, 0x92, 0xc9, 0xd4, 0x90, - 0x15, 0x28, 0x2b, 0x43, 0x8a, 0x04, 0xac, 0xc8, 0x9c, 0x71, 0xbc, 0x64, 0x9b, 0x8a, 0xb0, 0x92, - 0x28, 0x31, 0x56, 0x32, 0xbf, 0xe7, 0x27, 0x21, 0xae, 0x0e, 0x8b, 0xaa, 0x98, 0xaf, 0xc2, 0x96, - 0x0f, 0xc9, 0x44, 0x3c, 0x50, 0x96, 0xf5, 0xd8, 0x65, 0xcd, 0xbc, 0x72, 0xfc, 0xa1, 0x05, 0x55, - 0x5c, 0x1b, 0xa6, 0xda, 0x39, 0xef, 0xab, 0x68, 0x38, 0xae, 0xc9, 0x82, 0x93, 0x85, 0x89, 0x6d, - 0xa4, 0x84, 0x95, 0xd4, 0x84, 0xf4, 0xb4, 0xb0, 0xeb, 0x50, 0xe7, 0x25, 0x95, 0xfe, 0x84, 0x24, - 0x29, 0x48, 0xae, 0x41, 0xe5, 0x34, 0x1c, 0x4b, 0x5f, 0x14, 0xe4, 0x55, 0x51, 0x38, 0x76, 0x10, - 0x4f, 0xc7, 0xc3, 0xda, 0xe3, 0xd3, 0xe2, 0x1e, 0x46, 0x16, 0x66, 0x3e, 0x96, 0x6a, 0x56, 0x5f, - 0xa6, 0x0c, 0x6a, 0x6f, 0xc0, 0xe2, 0x41, 0x38, 0xa0, 0x5a, 0x48, 0x72, 0x26, 0x9f, 0xdb, 0xbf, - 0x6c, 0x41, 0x4d, 0x12, 0x93, 0x75, 0xa8, 0x30, 0xc7, 0x31, 0x73, 0xaa, 0x53, 0x57, 0xc4, 0x8c, - 0xce, 0x41, 0x0a, 0x66, 0x69, 0x31, 0x52, 0x94, 0x1e, 0x22, 0x64, 0x9c, 0x28, 0xf5, 0x91, 0xd5, - 0x70, 0x33, 0xae, 0x65, 0x06, 0xb5, 0xbf, 0x6b, 0xc1, 0x82, 0xd1, 0x07, 0xb9, 0x0e, 0x0d, 0xdf, - 0x8d, 0x13, 0x71, 0xed, 0x26, 0xb6, 0x47, 0x87, 0xf4, 0x8d, 0x2e, 0x99, 0x41, 0x6a, 0x15, 0x3e, - 0x2d, 0xeb, 0xe1, 0xd3, 0xdb, 0x50, 0x4f, 0x13, 0xf7, 0x2a, 0x86, 0x05, 0x65, 0x3d, 0xca, 0xcb, - 0xef, 0x94, 0x08, 0x23, 0x72, 0xa1, 0x1f, 0x46, 0xe2, 0x46, 0x87, 0x17, 0xec, 0x77, 0xa0, 0xa1, - 0xd1, 0xeb, 0x01, 0x3a, 0xcb, 0x08, 0xd0, 0xa9, 0xcc, 0x90, 0x52, 0x9a, 0x19, 0x62, 0xff, 0x9d, - 0x05, 0x0b, 0x8c, 0x07, 0xbd, 0x60, 0x78, 0x18, 0xfa, 0x5e, 0x7f, 0x8a, 0x7b, 0x2f, 0xd9, 0x4d, - 0xe8, 0x0c, 0xc9, 0x8b, 0x26, 0xcc, 0xb8, 0x5e, 0x86, 0x05, 0x84, 0x88, 0xaa, 0x32, 0x93, 0x61, - 0x26, 0x01, 0xc7, 0x6e, 0x2c, 0xc4, 0x42, 0xb8, 0x34, 0x06, 0xc8, 0x24, 0x8d, 0x01, 0x91, 0x9b, - 0xd0, 0xde, 0xc8, 0xf3, 0x7d, 0x8f, 0xd3, 0x72, 0x87, 0xb7, 0xa8, 0x8a, 0xf5, 0x39, 0xf0, 0x62, - 0xf7, 0x38, 0xbd, 0xa5, 0x50, 0x65, 0xfb, 0x2f, 0x4b, 0xd0, 0x90, 0x96, 0x71, 0x30, 0xa4, 0xe2, - 0x4a, 0x0d, 0x8f, 0x14, 0x4a, 0xc9, 0x68, 0x88, 0xac, 0x37, 0x0e, 0x21, 0x1a, 0x92, 0xdd, 0xf2, - 0x72, 0x7e, 0xcb, 0xaf, 0x42, 0x9d, 0xb1, 0xde, 0x1b, 0x78, 0xda, 0xe1, 0xd7, 0x71, 0x29, 0x20, - 0x6b, 0xef, 0x60, 0x6d, 0x35, 0xad, 0x45, 0xe0, 0xb9, 0x17, 0x70, 0x6f, 0x41, 0x53, 0x34, 0x83, - 0x7b, 0x82, 0x3a, 0x25, 0x65, 0x7e, 0x63, 0xbf, 0x1c, 0x83, 0x52, 0x7e, 0x79, 0x47, 0x7e, 0x59, - 0xbb, 0xe8, 0x4b, 0x49, 0x69, 0xdf, 0x57, 0xf7, 0x9a, 0xf7, 0x23, 0x77, 0x7c, 0x2a, 0xa5, 0xf4, - 0x36, 0x2c, 0x7b, 0x41, 0xdf, 0x9f, 0x0c, 0x68, 0x6f, 0x12, 0xb8, 0x41, 0x10, 0x4e, 0x82, 0x3e, - 0x95, 0x49, 0x1f, 0x45, 0x55, 0xf6, 0x40, 0xe5, 0xbc, 0x61, 0x43, 0x64, 0x03, 0xaa, 0xac, 0x23, - 0x69, 0x15, 0x8a, 0x45, 0x98, 0x93, 0x90, 0x75, 0xa8, 0xd2, 0xc1, 0x90, 0xca, 0x08, 0x00, 0xc9, - 0xf8, 0x3b, 0x83, 0x21, 0x75, 0x38, 0x01, 0x53, 0x28, 0x98, 0xd7, 0x68, 0x2a, 0x14, 0xd3, 0xa2, - 0xcc, 0xf5, 0x79, 0xe6, 0xe3, 0x0a, 0x90, 0x03, 0x2e, 0x03, 0xfa, 0x95, 0xc8, 0xaf, 0x96, 0xa1, - 0xa1, 0xc1, 0x4c, 0x37, 0x0c, 0xd9, 0x80, 0x7b, 0x03, 0xcf, 0x1d, 0xd1, 0x84, 0x46, 0x82, 0xef, - 0x33, 0x28, 0xa3, 0x73, 0xcf, 0x86, 0xbd, 0x70, 0x92, 0xf4, 0x06, 0x74, 0x18, 0x51, 0x6e, 0xe4, - 0x99, 0xd1, 0x31, 0x50, 0x46, 0x37, 0x72, 0x9f, 0xe9, 0x74, 0x9c, 0x83, 0x32, 0xa8, 0xbc, 0xe0, - 0xe0, 0x6b, 0x54, 0x49, 0x2f, 0x38, 0xf8, 0x8a, 0x64, 0xb5, 0x5a, 0xb5, 0x40, 0xab, 0xbd, 0x09, - 0x6b, 0x5c, 0x7f, 0x09, 0x49, 0xef, 0x65, 0x18, 0x6b, 0x46, 0x2d, 0xd9, 0x80, 0x36, 0x1b, 0xb3, - 0x14, 0x89, 0xd8, 0xfb, 0x06, 0x0f, 0x16, 0x5a, 0x4e, 0x0e, 0x67, 0xb4, 0x18, 0xb5, 0xd3, 0x69, - 0xf9, 0x85, 0x6f, 0x0e, 0x47, 0x5a, 0xf7, 0x99, 0x49, 0x5b, 0x17, 0xb4, 0x19, 0xdc, 0x5e, 0x80, - 0xc6, 0x51, 0x12, 0x8e, 0xe5, 0xa6, 0xb4, 0xa0, 0xc9, 0x8b, 0x22, 0xf9, 0xe6, 0x25, 0xb8, 0x82, - 0x5c, 0xf4, 0x28, 0x1c, 0x87, 0x7e, 0x38, 0x9c, 0x1a, 0x27, 0x86, 0x7f, 0xb0, 0x60, 0xd9, 0xa8, - 0x4d, 0x8f, 0x0c, 0x18, 0x6c, 0x90, 0x59, 0x13, 0x9c, 0xf1, 0x96, 0x34, 0xe5, 0xca, 0x09, 0x79, - 0x5c, 0xf7, 0xb1, 0x48, 0xa4, 0xd8, 0x82, 0x45, 0x39, 0x32, 0xf9, 0x21, 0xe7, 0xc2, 0x4e, 0x9e, - 0x0b, 0xc5, 0xf7, 0x2d, 0xf1, 0x81, 0x6c, 0xe2, 0xb3, 0xe2, 0xe2, 0x9c, 0x9f, 0x20, 0x64, 0x6c, - 0x49, 0x9d, 0x39, 0xf4, 0x13, 0xa6, 0x1c, 0x41, 0x5f, 0x81, 0xb1, 0xfd, 0x9b, 0x16, 0x40, 0x3a, - 0x3a, 0xbc, 0x6e, 0x55, 0x06, 0x82, 0xbf, 0xf6, 0xd0, 0x8c, 0xc1, 0xab, 0xd0, 0x54, 0xd7, 0x74, - 0xa9, 0xcd, 0x69, 0x48, 0x8c, 0x39, 0x8c, 0x37, 0x61, 0x71, 0xe8, 0x87, 0xc7, 0x68, 0xb0, 0x31, - 0x9b, 0x2b, 0x16, 0x29, 0x48, 0x2d, 0x0e, 0xdf, 0x13, 0x68, 0x6a, 0xa0, 0x2a, 0x9a, 0x81, 0xb2, - 0x7f, 0xab, 0xa4, 0x6e, 0x55, 0xd2, 0x39, 0xcf, 0x94, 0x32, 0x72, 0x27, 0xa7, 0x4e, 0x67, 0x5c, - 0x62, 0x60, 0x14, 0xf5, 0xf0, 0xc2, 0x20, 0xcf, 0x3b, 0xd0, 0x8a, 0xb8, 0xbe, 0x92, 0xca, 0xac, - 0xf2, 0x1c, 0x65, 0xb6, 0x10, 0x19, 0x56, 0xec, 0xe3, 0xd0, 0x76, 0x07, 0x67, 0x34, 0x4a, 0x3c, - 0x3c, 0x66, 0xa3, 0x0b, 0xc1, 0x55, 0xf0, 0xa2, 0x86, 0xa3, 0x65, 0xbf, 0x09, 0x8b, 0x22, 0xed, - 0x4b, 0x51, 0x8a, 0x14, 0xee, 0x14, 0x66, 0x84, 0xf6, 0x1f, 0xcb, 0x0b, 0x1c, 0x73, 0x0f, 0x67, - 0xaf, 0x88, 0x3e, 0xbb, 0x52, 0x66, 0x76, 0x1f, 0x13, 0x97, 0x29, 0x03, 0x79, 0x96, 0x2f, 0x6b, - 0x49, 0x16, 0x03, 0x71, 0xf9, 0x65, 0x2e, 0x69, 0xe5, 0x45, 0x96, 0xd4, 0xfe, 0x81, 0x05, 0xf3, - 0x7b, 0xe1, 0x78, 0x4f, 0xa4, 0x9b, 0xa0, 0x20, 0xa8, 0x7c, 0x4b, 0x59, 0x7c, 0x4e, 0x22, 0x4a, - 0xa1, 0xe5, 0x5e, 0xc8, 0x5a, 0xee, 0x9f, 0x87, 0x97, 0x30, 0x92, 0x14, 0x85, 0xe3, 0x30, 0x62, - 0xc2, 0xe8, 0xfa, 0xdc, 0x4c, 0x87, 0x41, 0x72, 0x2a, 0xd5, 0xd8, 0xf3, 0x48, 0xf0, 0x78, 0xc7, - 0x8e, 0x25, 0xdc, 0xe9, 0x16, 0x9e, 0x06, 0xd7, 0x6e, 0xf9, 0x0a, 0xfb, 0x33, 0x50, 0x47, 0x57, - 0x19, 0xa7, 0xf5, 0x3a, 0xd4, 0x4f, 0xc3, 0x71, 0xef, 0xd4, 0x0b, 0x12, 0x29, 0xdc, 0xad, 0xd4, - 0x87, 0xdd, 0xc3, 0x05, 0x51, 0x04, 0xf6, 0x37, 0xe7, 0x60, 0xfe, 0x41, 0x70, 0x16, 0x7a, 0x7d, - 0xbc, 0x2c, 0x1a, 0xd1, 0x51, 0x28, 0xb3, 0x4f, 0xd9, 0xff, 0xe4, 0x2a, 0xcc, 0x63, 0xba, 0xd5, - 0x98, 0x33, 0x6d, 0x93, 0x5f, 0xea, 0x0a, 0x88, 0x39, 0x09, 0x51, 0x9a, 0xf8, 0xce, 0xc5, 0x47, - 0x43, 0xd8, 0x21, 0x22, 0xd2, 0x13, 0xd7, 0x45, 0x29, 0xcd, 0xee, 0xad, 0x6a, 0xd9, 0xbd, 0xac, - 0x2f, 0x91, 0x1e, 0xc3, 0xf3, 0x27, 0x78, 0x5f, 0x02, 0xc2, 0x83, 0x4f, 0x44, 0x79, 0x24, 0x10, - 0x5d, 0x8e, 0x79, 0x71, 0xf0, 0xd1, 0x41, 0xe6, 0x96, 0xf0, 0x0f, 0x38, 0x0d, 0x57, 0xc2, 0x3a, - 0xc4, 0x5c, 0xb8, 0xec, 0xa3, 0x84, 0x3a, 0xe7, 0xfd, 0x0c, 0xcc, 0x34, 0xf5, 0x80, 0x2a, 0x85, - 0xca, 0xe7, 0x01, 0x3c, 0xb9, 0x3f, 0x8b, 0x6b, 0xc7, 0x25, 0x9e, 0x19, 0x27, 0x8f, 0x4b, 0x8c, - 0x61, 0x5c, 0xdf, 0x3f, 0x76, 0xfb, 0x4f, 0xf1, 0xcd, 0x09, 0x5e, 0xdf, 0xd4, 0x1d, 0x13, 0xc4, - 0x24, 0x97, 0x74, 0x57, 0xf1, 0xfa, 0xbb, 0xe2, 0xe8, 0x10, 0xb9, 0x03, 0x0d, 0x3c, 0x22, 0x8a, - 0x7d, 0x6d, 0xe1, 0xbe, 0xb6, 0xf5, 0x33, 0x24, 0xee, 0xac, 0x4e, 0xa4, 0x5f, 0x64, 0x2d, 0xe6, - 0x72, 0xd5, 0xdc, 0xc1, 0x40, 0xdc, 0xff, 0xb5, 0xb1, 0xb7, 0x14, 0x60, 0x56, 0x55, 0x2c, 0x18, - 0x27, 0x58, 0x42, 0x02, 0x03, 0x23, 0xd7, 0xa0, 0xc6, 0x8e, 0x2f, 0x63, 0xd7, 0x1b, 0x60, 0xb2, - 0x1b, 0x3f, 0x45, 0x29, 0x8c, 0xb5, 0x21, 0xff, 0xc7, 0x7b, 0xba, 0x65, 0x5c, 0x15, 0x03, 0x63, - 0x6b, 0xa3, 0xca, 0x28, 0x4c, 0x2b, 0x7c, 0x47, 0x0d, 0x90, 0xbc, 0x81, 0xb7, 0x30, 0x09, 0xed, - 0xac, 0x62, 0x94, 0xe7, 0x25, 0x31, 0x67, 0xc1, 0xb4, 0xf2, 0xef, 0x11, 0x23, 0x71, 0x38, 0xa5, - 0xfd, 0x49, 0x68, 0xea, 0x30, 0xa9, 0x41, 0xe5, 0xe1, 0xe1, 0xee, 0x41, 0xfb, 0x12, 0x69, 0xc0, - 0xfc, 0xd1, 0xee, 0xa3, 0x47, 0xfb, 0xbb, 0x3b, 0x6d, 0x8b, 0x34, 0xa1, 0xa6, 0x32, 0x92, 0x4a, - 0x76, 0x02, 0x64, 0x6b, 0x30, 0x10, 0xdf, 0xa9, 0x63, 0x7b, 0xca, 0xc1, 0x96, 0xc1, 0xc1, 0x05, - 0x5c, 0x54, 0x2a, 0xe6, 0xa2, 0xe7, 0xae, 0xb5, 0xbd, 0x0b, 0x8d, 0x43, 0xed, 0x45, 0x06, 0x0a, - 0x94, 0x7c, 0x8b, 0x21, 0x04, 0x51, 0x43, 0xb4, 0xe1, 0x94, 0xf4, 0xe1, 0xd8, 0x7f, 0x62, 0xf1, - 0x2c, 0x71, 0x35, 0x7c, 0xde, 0xb7, 0x0d, 0x4d, 0x15, 0x5c, 0x49, 0xd3, 0x0b, 0x0d, 0x8c, 0xd1, - 0xe0, 0x50, 0x7a, 0xe1, 0xc9, 0x49, 0x4c, 0x65, 0x32, 0x90, 0x81, 0x31, 0x49, 0x60, 0x3e, 0x15, - 0xf3, 0x4f, 0x3c, 0xde, 0x43, 0x2c, 0x92, 0x82, 0x72, 0x38, 0xd3, 0xeb, 0x11, 0x3d, 0xa3, 0x51, - 0xac, 0xd2, 0xa0, 0x54, 0x59, 0x65, 0x41, 0x66, 0x57, 0x79, 0x03, 0x6a, 0xaa, 0x5d, 0x53, 0x65, - 0x49, 0x4a, 0x55, 0xcf, 0x54, 0x23, 0x9e, 0x32, 0x8c, 0x41, 0x73, 0x35, 0x9d, 0xaf, 0x20, 0xb7, - 0x80, 0x9c, 0x78, 0x51, 0x96, 0xbc, 0x8c, 0xe4, 0x05, 0x35, 0xf6, 0x13, 0x58, 0x96, 0xac, 0xa3, - 0x39, 0x53, 0xe6, 0x26, 0x5a, 0x17, 0x09, 0x4c, 0x29, 0x2f, 0x30, 0xf6, 0xff, 0x58, 0x30, 0x2f, - 0x76, 0x3a, 0xf7, 0xaa, 0x87, 0xef, 0xb3, 0x81, 0x91, 0x8e, 0xf1, 0x00, 0x02, 0xa5, 0x4b, 0xa8, - 0xc9, 0x9c, 0x22, 0x2c, 0x17, 0x29, 0x42, 0x02, 0x95, 0xb1, 0x9b, 0x9c, 0xe2, 0xd9, 0xb9, 0xee, - 0xe0, 0xff, 0xa4, 0xcd, 0x23, 0x3d, 0x5c, 0xe9, 0x62, 0x94, 0xa7, 0xe8, 0xfd, 0x12, 0xb7, 0xef, - 0xf9, 0xf7, 0x4b, 0x57, 0xa1, 0x8e, 0x03, 0xe8, 0xa5, 0x81, 0x9c, 0x14, 0x60, 0x9c, 0xcb, 0x0b, - 0x28, 0xc9, 0x22, 0x17, 0x39, 0x45, 0xec, 0x55, 0xbe, 0xf3, 0x62, 0x09, 0xd4, 0x9d, 0xa9, 0xc8, - 0x3a, 0x4d, 0xe1, 0x94, 0x23, 0xc4, 0x00, 0xb2, 0x1c, 0x21, 0x48, 0x1d, 0x55, 0x6f, 0x77, 0xa1, - 0xb3, 0x43, 0x7d, 0x9a, 0xd0, 0x2d, 0xdf, 0xcf, 0xb6, 0xff, 0x12, 0x5c, 0x29, 0xa8, 0x13, 0xfe, - 0xf3, 0x17, 0x61, 0x75, 0x8b, 0x67, 0xe8, 0xfd, 0xa4, 0xb2, 0x4e, 0xec, 0x0e, 0xac, 0x65, 0x9b, - 0x14, 0x9d, 0xdd, 0x83, 0xa5, 0x1d, 0x7a, 0x3c, 0x19, 0xee, 0xd3, 0xb3, 0xb4, 0x23, 0x02, 0x95, - 0xf8, 0x34, 0x3c, 0x17, 0x82, 0x89, 0xff, 0x93, 0x97, 0x01, 0x7c, 0x46, 0xd3, 0x8b, 0xc7, 0xb4, - 0x2f, 0xdf, 0x1c, 0x20, 0x72, 0x34, 0xa6, 0x7d, 0xfb, 0x4d, 0x20, 0x7a, 0x3b, 0x62, 0xbd, 0x98, - 0xdd, 0x9b, 0x1c, 0xf7, 0xe2, 0x69, 0x9c, 0xd0, 0x91, 0x7c, 0x4c, 0xa1, 0x43, 0xf6, 0x4d, 0x68, - 0x1e, 0xba, 0x53, 0x87, 0x7e, 0x5d, 0x3c, 0xe6, 0xba, 0x0c, 0xf3, 0x63, 0x77, 0xca, 0xd4, 0x94, - 0x8a, 0x30, 0x61, 0xb5, 0xfd, 0x5f, 0x25, 0x98, 0xe3, 0x94, 0xac, 0xd5, 0x01, 0x8d, 0x13, 0x2f, - 0x40, 0xc6, 0x92, 0xad, 0x6a, 0x50, 0x8e, 0x95, 0x4b, 0x05, 0xac, 0x2c, 0x4e, 0x69, 0x32, 0x7f, - 0x5b, 0xf0, 0xab, 0x81, 0x31, 0xe6, 0x4a, 0xd3, 0xbf, 0x78, 0x88, 0x23, 0x05, 0x32, 0xc1, 0xc8, - 0xd4, 0xba, 0xf2, 0xf1, 0x49, 0x29, 0x15, 0x9c, 0xab, 0x43, 0x85, 0x36, 0x7c, 0x9e, 0x33, 0x78, - 0xce, 0x86, 0xe7, 0x6c, 0x75, 0xed, 0x05, 0x6c, 0x35, 0x3f, 0xba, 0x3d, 0xcf, 0x56, 0xc3, 0x0b, - 0xd8, 0x6a, 0x9b, 0x40, 0xfb, 0x1e, 0xa5, 0x0e, 0x65, 0xde, 0xa0, 0xe4, 0xdd, 0x6f, 0x59, 0xd0, - 0x16, 0x5c, 0xa4, 0xea, 0xc8, 0xab, 0x86, 0xd7, 0x5b, 0x98, 0x47, 0x7d, 0x03, 0x16, 0xd0, 0x17, - 0x55, 0x51, 0x57, 0x11, 0x22, 0x36, 0x40, 0x36, 0x0f, 0x79, 0xdd, 0x39, 0xf2, 0x7c, 0xb1, 0x29, - 0x3a, 0x24, 0x03, 0xb7, 0x91, 0x2b, 0xd2, 0xa0, 0x2c, 0x47, 0x95, 0xed, 0xbf, 0xb2, 0x60, 0x49, - 0x1b, 0xb0, 0xe0, 0xc2, 0x77, 0x40, 0x4a, 0x03, 0x0f, 0xc1, 0x72, 0xc9, 0xbd, 0x6c, 0x8a, 0x4d, - 0xfa, 0x99, 0x41, 0x8c, 0x9b, 0xe9, 0x4e, 0x71, 0x80, 0xf1, 0x64, 0x24, 0x94, 0xa8, 0x0e, 0x31, - 0x46, 0x3a, 0xa7, 0xf4, 0xa9, 0x22, 0xe1, 0x6a, 0xdc, 0xc0, 0x30, 0x47, 0x87, 0xf9, 0xd0, 0x8a, - 0x88, 0xdb, 0x33, 0x13, 0xb4, 0xff, 0xc5, 0x82, 0x65, 0x7e, 0x18, 0x12, 0x47, 0x4d, 0xf5, 0x04, - 0x66, 0x8e, 0x9f, 0xfe, 0xb8, 0x44, 0xee, 0x5d, 0x72, 0x44, 0x99, 0x7c, 0xfa, 0x05, 0x0f, 0x70, - 0x2a, 0x37, 0x6b, 0xc6, 0x5e, 0x94, 0x8b, 0xf6, 0xe2, 0x39, 0x2b, 0x5d, 0x14, 0x72, 0xac, 0x16, - 0x86, 0x1c, 0xef, 0xce, 0x43, 0x35, 0xee, 0x87, 0x63, 0x6a, 0xaf, 0xc1, 0x8a, 0x39, 0x39, 0xa1, - 0x82, 0xbe, 0x63, 0x41, 0xe7, 0x1e, 0x0f, 0xcd, 0x7b, 0xc1, 0x70, 0xcf, 0x8b, 0x93, 0x30, 0x52, - 0x2f, 0x05, 0xaf, 0x01, 0xc4, 0x89, 0x1b, 0x25, 0x3c, 0x03, 0x57, 0x04, 0x04, 0x53, 0x84, 0x8d, - 0x91, 0x06, 0x03, 0x5e, 0xcb, 0xf7, 0x46, 0x95, 0x73, 0x3e, 0x84, 0x38, 0xae, 0x19, 0x96, 0xf8, - 0x35, 0x9e, 0xab, 0xc8, 0x7c, 0x05, 0x7a, 0x86, 0x7a, 0x9d, 0x9f, 0x83, 0x32, 0xa8, 0xfd, 0x4f, - 0x16, 0x2c, 0xa6, 0x83, 0xc4, 0x5b, 0x3c, 0x53, 0x3b, 0x08, 0xf3, 0x9b, 0x6a, 0x07, 0x19, 0xaa, - 0xf4, 0x98, 0x3d, 0x16, 0x63, 0xd3, 0x10, 0x94, 0x58, 0x51, 0x0a, 0x27, 0xd2, 0xc1, 0xd1, 0x21, - 0x9e, 0x79, 0xc4, 0x3c, 0x01, 0xe1, 0xd5, 0x88, 0x12, 0x26, 0x50, 0x8f, 0x12, 0xfc, 0x6a, 0x8e, - 0x1f, 0x04, 0x45, 0x51, 0x9a, 0xd2, 0x79, 0x44, 0xd1, 0x94, 0xea, 0xd7, 0x1c, 0x35, 0xbe, 0x3e, - 0xb2, 0x6c, 0xff, 0xb6, 0x05, 0x57, 0x0a, 0x16, 0x5e, 0x48, 0xcd, 0x0e, 0x2c, 0x9d, 0xa8, 0x4a, - 0xb9, 0x38, 0x5c, 0x74, 0xd6, 0xe4, 0x3d, 0x93, 0xb9, 0x20, 0x4e, 0xfe, 0x03, 0xe5, 0x17, 0xf1, - 0xe5, 0x36, 0x72, 0xfb, 0xf2, 0x15, 0x1b, 0x9f, 0x83, 0x86, 0xf6, 0x46, 0x8f, 0x5c, 0x86, 0xe5, - 0x27, 0x0f, 0x1e, 0x1d, 0xec, 0x1e, 0x1d, 0xf5, 0x0e, 0x1f, 0xdf, 0xfd, 0xc2, 0xee, 0x97, 0x7b, - 0x7b, 0x5b, 0x47, 0x7b, 0xed, 0x4b, 0x64, 0x0d, 0xc8, 0xc1, 0xee, 0xd1, 0xa3, 0xdd, 0x1d, 0x03, - 0xb7, 0xee, 0xfc, 0x4e, 0x19, 0x5a, 0xfc, 0xfe, 0x92, 0xff, 0xba, 0x03, 0x8d, 0xc8, 0xbb, 0x30, - 0x2f, 0x7e, 0x9d, 0x83, 0xac, 0x8a, 0x61, 0x9b, 0xbf, 0x07, 0xd2, 0x5d, 0xcb, 0xc2, 0x82, 0x2f, - 0x97, 0x7f, 0xe5, 0x07, 0xff, 0xfe, 0x7b, 0xa5, 0x05, 0xd2, 0xd8, 0x3c, 0x7b, 0x63, 0x73, 0x48, - 0x83, 0x98, 0xb5, 0xf1, 0x55, 0x80, 0xf4, 0x77, 0x2b, 0x48, 0x47, 0xf9, 0x83, 0x99, 0x1f, 0xe4, - 0xe8, 0x5e, 0x29, 0xa8, 0x11, 0xed, 0x5e, 0xc1, 0x76, 0x97, 0xed, 0x16, 0x6b, 0xd7, 0x0b, 0xbc, - 0x84, 0xff, 0x88, 0xc5, 0xdb, 0xd6, 0x06, 0x19, 0x40, 0x53, 0xff, 0x59, 0x0a, 0x22, 0xc3, 0x50, - 0x05, 0x3f, 0x8a, 0xd1, 0x7d, 0xa9, 0xb0, 0x4e, 0xc6, 0xe0, 0xb0, 0x8f, 0x55, 0xbb, 0xcd, 0xfa, - 0x98, 0x20, 0x45, 0xda, 0x8b, 0x0f, 0x2d, 0xf3, 0xd7, 0x27, 0xc8, 0x55, 0x4d, 0x65, 0xe4, 0x7e, - 0xfb, 0xa2, 0xfb, 0xf2, 0x8c, 0x5a, 0xd1, 0xd7, 0xcb, 0xd8, 0xd7, 0x65, 0x9b, 0xb0, 0xbe, 0xfa, - 0x48, 0x23, 0x7f, 0xfb, 0xe2, 0x6d, 0x6b, 0xe3, 0xce, 0xdf, 0x5e, 0x87, 0xba, 0x0a, 0x1c, 0x93, - 0xf7, 0x61, 0xc1, 0xb8, 0x60, 0x26, 0x72, 0x1a, 0x45, 0xf7, 0xd1, 0xdd, 0xab, 0xc5, 0x95, 0xa2, - 0xe3, 0x6b, 0xd8, 0x71, 0x87, 0xac, 0xb1, 0x8e, 0xc5, 0x0d, 0xed, 0x26, 0xa6, 0x4a, 0xf0, 0xbc, - 0xe7, 0xa7, 0x7c, 0x9e, 0xe9, 0xa5, 0xb0, 0x31, 0xcf, 0xdc, 0x25, 0xb2, 0x31, 0xcf, 0xfc, 0x4d, - 0xb2, 0x7d, 0x15, 0xbb, 0x5b, 0x23, 0x2b, 0x7a, 0x77, 0x2a, 0xa0, 0x4b, 0x31, 0x59, 0x5f, 0xff, - 0xc1, 0x06, 0xf2, 0xb2, 0x62, 0xac, 0xa2, 0x1f, 0x72, 0x50, 0x2c, 0x92, 0xff, 0x35, 0x07, 0xbb, - 0x83, 0x5d, 0x11, 0x82, 0xdb, 0xa7, 0xff, 0x5e, 0x03, 0xf9, 0x0a, 0xd4, 0xd5, 0x03, 0x5d, 0x72, - 0x59, 0x7b, 0x30, 0xad, 0x3f, 0x28, 0xee, 0x76, 0xf2, 0x15, 0x45, 0x8c, 0xa1, 0xb7, 0xcc, 0x18, - 0xe3, 0x09, 0x34, 0xb4, 0x47, 0xb8, 0xe4, 0x8a, 0x0a, 0xfb, 0x67, 0x1f, 0xfa, 0x76, 0xbb, 0x45, - 0x55, 0xa2, 0x8b, 0x25, 0xec, 0xa2, 0x41, 0xea, 0xc8, 0x7b, 0xc9, 0xb3, 0x30, 0x26, 0xfb, 0xb0, - 0x2a, 0x0e, 0x2e, 0xc7, 0xf4, 0xa3, 0x2c, 0x51, 0xc1, 0xef, 0x57, 0xdc, 0xb6, 0xc8, 0x3b, 0x50, - 0x93, 0x6f, 0xad, 0xc9, 0x5a, 0xf1, 0x9b, 0xf1, 0xee, 0xe5, 0x1c, 0x2e, 0xd4, 0xda, 0x97, 0x01, - 0xd2, 0x17, 0xbf, 0x4a, 0x80, 0x73, 0x2f, 0x88, 0xd5, 0xee, 0xe4, 0x9f, 0x07, 0xdb, 0x6b, 0x38, - 0xc1, 0x36, 0x41, 0x01, 0x0e, 0xe8, 0xb9, 0x7c, 0xbe, 0xf2, 0x35, 0x68, 0x68, 0x8f, 0x7e, 0xd5, - 0xf2, 0xe5, 0x1f, 0x0c, 0xab, 0xe5, 0x2b, 0x78, 0x23, 0x6c, 0x77, 0xb1, 0xf5, 0x15, 0x7b, 0x91, - 0xb5, 0x1e, 0x7b, 0xc3, 0x60, 0xc4, 0x09, 0xd8, 0x06, 0x9d, 0xc2, 0x82, 0xf1, 0xb2, 0x57, 0x49, - 0x4f, 0xd1, 0xbb, 0x61, 0x25, 0x3d, 0x85, 0x8f, 0x81, 0x25, 0x3b, 0xdb, 0x4b, 0xac, 0x9f, 0x33, - 0x24, 0xd1, 0x7a, 0x7a, 0x0f, 0x1a, 0xda, 0x2b, 0x5d, 0x35, 0x97, 0xfc, 0x83, 0x60, 0x35, 0x97, - 0xa2, 0x47, 0xbd, 0x2b, 0xd8, 0x47, 0xcb, 0x46, 0x56, 0xc0, 0xd7, 0x1f, 0xac, 0xed, 0xf7, 0xa1, - 0x65, 0xbe, 0xdb, 0x55, 0x72, 0x59, 0xf8, 0x02, 0x58, 0xc9, 0xe5, 0x8c, 0xc7, 0xbe, 0x82, 0xa5, - 0x37, 0x96, 0x55, 0x27, 0x9b, 0x1f, 0x88, 0x6b, 0xdc, 0x0f, 0xc9, 0x17, 0x99, 0xf2, 0x11, 0xcf, - 0x71, 0xc8, 0x65, 0x8d, 0x6b, 0xf5, 0x47, 0x3b, 0x4a, 0x5e, 0x72, 0x2f, 0x77, 0x4c, 0x66, 0xe6, - 0xef, 0x57, 0xd0, 0xa2, 0xe0, 0xb3, 0x1c, 0xcd, 0xa2, 0xe8, 0x2f, 0x77, 0x34, 0x8b, 0x62, 0xbc, - 0xde, 0xc9, 0x5a, 0x94, 0xc4, 0x63, 0x6d, 0x04, 0xb0, 0x98, 0x49, 0x50, 0x53, 0x52, 0x51, 0x9c, - 0xd1, 0xdb, 0xbd, 0xf6, 0xfc, 0xbc, 0x36, 0x53, 0x51, 0x49, 0x05, 0xb5, 0x29, 0xf3, 0xa7, 0x7f, - 0x11, 0x9a, 0xfa, 0x8b, 0x4a, 0xa2, 0x8b, 0x72, 0xb6, 0xa7, 0x97, 0x0a, 0xeb, 0xcc, 0xcd, 0x25, - 0x4d, 0xbd, 0x1b, 0xf2, 0x25, 0x58, 0x53, 0xa2, 0xae, 0xe7, 0x3c, 0xc5, 0xe4, 0x95, 0x82, 0x4c, - 0x28, 0x3d, 0x9c, 0xd1, 0xbd, 0x32, 0x33, 0x55, 0xea, 0xb6, 0xc5, 0x98, 0xc6, 0x7c, 0xaa, 0x96, - 0x2a, 0xf3, 0xa2, 0x17, 0x7a, 0xa9, 0x32, 0x2f, 0x7c, 0xdf, 0x26, 0x99, 0x86, 0x2c, 0x1b, 0x6b, - 0xc4, 0x23, 0xf9, 0xe4, 0x3d, 0x58, 0xd4, 0xb2, 0x4a, 0x8f, 0xa6, 0x41, 0x5f, 0x09, 0x40, 0xfe, - 0xf9, 0x41, 0xb7, 0xc8, 0xdf, 0xb6, 0x2f, 0x63, 0xfb, 0x4b, 0xb6, 0xb1, 0x38, 0x8c, 0xf9, 0xb7, - 0xa1, 0xa1, 0x67, 0xac, 0x3e, 0xa7, 0xdd, 0xcb, 0x5a, 0x95, 0x9e, 0x3d, 0x7f, 0xdb, 0x22, 0x7f, - 0x60, 0x41, 0xd3, 0xc8, 0xff, 0x34, 0xee, 0xab, 0x32, 0xed, 0x74, 0xf4, 0x3a, 0xbd, 0x21, 0xdb, - 0xc1, 0x41, 0xee, 0x6f, 0x7c, 0xde, 0x58, 0x84, 0x0f, 0x8c, 0x73, 0xdb, 0xad, 0xec, 0x0f, 0x96, - 0x7c, 0x98, 0x25, 0xd0, 0x9f, 0x68, 0x7c, 0x78, 0xdb, 0x22, 0xdf, 0xb5, 0xa0, 0x65, 0x46, 0x1b, - 0xd4, 0x56, 0x15, 0xc6, 0x35, 0xd4, 0x56, 0xcd, 0x08, 0x51, 0xbc, 0x87, 0xa3, 0x7c, 0xb4, 0xe1, - 0x18, 0xa3, 0x14, 0x8f, 0x18, 0x7f, 0xbc, 0xd1, 0x92, 0xb7, 0xf9, 0x8f, 0x16, 0xc9, 0x10, 0x18, - 0xd1, 0xac, 0x46, 0x76, 0x7b, 0xf5, 0xdf, 0xe1, 0x59, 0xb7, 0x6e, 0x5b, 0xe4, 0x6b, 0xfc, 0x77, - 0x4d, 0xc4, 0xb7, 0xc8, 0x25, 0x2f, 0xfa, 0xbd, 0x7d, 0x03, 0xe7, 0x74, 0xcd, 0xbe, 0x62, 0xcc, - 0x29, 0x6b, 0x8f, 0xb7, 0xf8, 0xe8, 0xc4, 0x4f, 0xe8, 0xa4, 0x06, 0x25, 0xf7, 0xb3, 0x3a, 0xb3, - 0x07, 0x39, 0xe2, 0x83, 0x14, 0xe4, 0x06, 0x2b, 0xbf, 0x60, 0x33, 0xf6, 0x06, 0x8e, 0xf5, 0x86, - 0xfd, 0xca, 0xcc, 0xb1, 0x6e, 0x62, 0xcc, 0x80, 0x8d, 0xf8, 0x10, 0x20, 0x0d, 0x57, 0x93, 0x4c, - 0xb8, 0x54, 0x09, 0x78, 0x3e, 0xa2, 0x6d, 0xca, 0x8b, 0x8c, 0xaa, 0xb2, 0x16, 0xbf, 0xc2, 0xd5, - 0xd5, 0x03, 0x19, 0x68, 0xd5, 0x9d, 0x12, 0x33, 0xae, 0x6c, 0x38, 0x25, 0xd9, 0xf6, 0x0d, 0x65, - 0xa5, 0xa2, 0xb6, 0x8f, 0x61, 0x61, 0x3f, 0x0c, 0x9f, 0x4e, 0xc6, 0xea, 0xb2, 0xc9, 0x0c, 0xe7, - 0xed, 0xb9, 0xf1, 0x69, 0x37, 0x33, 0x0b, 0xfb, 0x3a, 0x36, 0xd5, 0x25, 0x1d, 0xad, 0xa9, 0xcd, - 0x0f, 0xd2, 0x70, 0xf8, 0x87, 0xc4, 0x85, 0x25, 0xa5, 0x03, 0xd5, 0xc0, 0xbb, 0x66, 0x33, 0x86, - 0xe6, 0xcb, 0x76, 0x61, 0x78, 0xb6, 0x72, 0xb4, 0x9b, 0xb1, 0x6c, 0xf3, 0xb6, 0x45, 0x0e, 0xa1, - 0xb9, 0x43, 0xfb, 0xe1, 0x80, 0x8a, 0x98, 0xd8, 0x72, 0x3a, 0x70, 0x15, 0x4c, 0xeb, 0x2e, 0x18, - 0xa0, 0x69, 0x17, 0xc6, 0xee, 0x34, 0xa2, 0x5f, 0xdf, 0xfc, 0x40, 0x44, 0xdb, 0x3e, 0x94, 0x76, - 0x41, 0x86, 0x23, 0x0d, 0xbb, 0x90, 0x89, 0x5f, 0x1a, 0x76, 0x21, 0x17, 0xbf, 0x34, 0x96, 0x5a, - 0x86, 0x43, 0x89, 0x0f, 0x4b, 0xb9, 0x90, 0xa7, 0x32, 0x09, 0xb3, 0x02, 0xa5, 0xdd, 0xeb, 0xb3, - 0x09, 0xcc, 0xde, 0x36, 0xcc, 0xde, 0x8e, 0x60, 0x61, 0x87, 0xf2, 0xc5, 0xe2, 0x19, 0x2d, 0x99, - 0x24, 0x62, 0x3d, 0x5f, 0x26, 0xab, 0xc0, 0xb1, 0xce, 0x34, 0xfc, 0x98, 0x4e, 0x42, 0xbe, 0x02, - 0x8d, 0xfb, 0x34, 0x91, 0x29, 0x2c, 0xca, 0xf5, 0xcc, 0xe4, 0xb4, 0x74, 0x0b, 0x32, 0x60, 0x4c, - 0x9e, 0xc1, 0xd6, 0x36, 0xe9, 0x60, 0x48, 0xb9, 0x72, 0xea, 0x79, 0x83, 0x0f, 0xc9, 0x2f, 0x60, - 0xe3, 0x2a, 0x87, 0x6e, 0x4d, 0xcb, 0x7c, 0xd0, 0x1b, 0x5f, 0xcc, 0xe0, 0x45, 0x2d, 0x07, 0xe1, - 0x80, 0x6a, 0x2e, 0x50, 0x00, 0x0d, 0x2d, 0xf5, 0x53, 0x09, 0x50, 0x3e, 0x8d, 0x55, 0x09, 0x50, - 0x41, 0xa6, 0xa8, 0xbd, 0x8e, 0xfd, 0xd8, 0xe4, 0x7a, 0xda, 0x0f, 0xcf, 0x0e, 0x4d, 0x7b, 0xda, - 0xfc, 0xc0, 0x1d, 0x25, 0x1f, 0x92, 0x27, 0xf8, 0x92, 0x59, 0x4f, 0xd3, 0x49, 0x7d, 0xe9, 0x6c, - 0x46, 0x8f, 0x5a, 0x2c, 0xad, 0xca, 0xf4, 0xaf, 0x79, 0x57, 0xe8, 0x29, 0x7d, 0x1a, 0xe0, 0x28, - 0x09, 0xc7, 0x3b, 0x2e, 0x1d, 0x85, 0x41, 0xaa, 0x6b, 0xd3, 0x54, 0x94, 0x54, 0x7f, 0x69, 0xf9, - 0x28, 0xe4, 0x89, 0x76, 0xf8, 0x30, 0xb2, 0x9c, 0x24, 0x73, 0xcd, 0xcc, 0x56, 0x51, 0x0b, 0x52, - 0x90, 0xb1, 0x72, 0xdb, 0x22, 0x5b, 0x00, 0x69, 0xcc, 0x5b, 0x1d, 0x25, 0x72, 0xe1, 0x74, 0xa5, - 0xf6, 0x0a, 0x02, 0xe4, 0x87, 0x50, 0x4f, 0x83, 0xa8, 0x97, 0xd3, 0xf4, 0x5d, 0x23, 0xe4, 0xaa, - 0x2c, 0x78, 0x2e, 0xb4, 0x69, 0xb7, 0x71, 0xa9, 0x80, 0xd4, 0xd8, 0x52, 0x61, 0xbc, 0xd2, 0x83, - 0x65, 0x3e, 0x40, 0xe5, 0x8e, 0x60, 0x72, 0x85, 0x9c, 0x49, 0x41, 0x78, 0x51, 0x49, 0x73, 0x61, - 0x74, 0xce, 0x88, 0x56, 0x30, 0x6e, 0xe5, 0x89, 0x1d, 0x4c, 0x35, 0x8f, 0x60, 0x29, 0x17, 0x3e, - 0x52, 0x22, 0x3d, 0x2b, 0xa2, 0xa7, 0x44, 0x7a, 0x66, 0xe4, 0xc9, 0x5e, 0xc5, 0x2e, 0x17, 0x6d, - 0xc0, 0x13, 0xd0, 0xb9, 0x97, 0xf4, 0x4f, 0xdf, 0xb6, 0x36, 0xee, 0xde, 0x7c, 0xef, 0xa7, 0x86, - 0x5e, 0x72, 0x3a, 0x39, 0xbe, 0xd5, 0x0f, 0x47, 0x9b, 0xbe, 0x0c, 0x29, 0x88, 0x14, 0xa9, 0x4d, - 0x3f, 0x18, 0x6c, 0x62, 0xcb, 0xc7, 0x73, 0xf8, 0xcb, 0xaf, 0x9f, 0xfc, 0xdf, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x7d, 0x0e, 0xcf, 0xb2, 0x2b, 0x56, 0x00, 0x00, +func init() { proto.RegisterFile("rpc.proto", fileDescriptor_rpc_2f0f5e700a80a784) } + +var fileDescriptor_rpc_2f0f5e700a80a784 = []byte{ + // 7064 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7c, 0x5f, 0x6c, 0x24, 0xd9, + 0x59, 0xef, 0x54, 0xbb, 0xdb, 0xee, 0xfe, 0xba, 0xdd, 0x6e, 0x1f, 0xff, 0x99, 0x9e, 0xde, 0xd9, + 0xd9, 0xd9, 0x93, 0xb9, 0x3b, 0x5e, 0x67, 0xef, 0x78, 0x76, 0x92, 0xec, 0xdd, 0xec, 0x26, 0xb9, + 0xd7, 0x63, 0x7b, 0xc6, 0x93, 0x78, 0x3d, 0x4e, 0x79, 0x26, 0x73, 0xb3, 0x09, 0xea, 0x94, 0xbb, + 0x8f, 0xdb, 0xb5, 0xd3, 0x5d, 0xd5, 0xa9, 0xaa, 0xb6, 0xc7, 0x59, 0x56, 0x42, 0x80, 0x88, 0x84, + 0x40, 0x08, 0x78, 0x21, 0x28, 0x08, 0x29, 0x20, 0x41, 0x1e, 0x79, 0x08, 0x42, 0x02, 0xde, 0x10, + 0x12, 0x48, 0x08, 0x41, 0x1e, 0x91, 0x78, 0x21, 0x2f, 0x81, 0x37, 0x24, 0x1e, 0x91, 0xd0, 0xf9, + 0xce, 0x9f, 0x3a, 0xa7, 0xaa, 0x7a, 0x3c, 0x9b, 0x04, 0x9e, 0xec, 0xf3, 0x3b, 0x5f, 0x9d, 0xbf, + 0xdf, 0xbf, 0xf3, 0x9d, 0xef, 0x34, 0xd4, 0xa2, 0x71, 0xef, 0xd6, 0x38, 0x0a, 0x93, 0x90, 0x54, + 0x86, 0x41, 0x34, 0xee, 0x75, 0xae, 0x0e, 0xc2, 0x70, 0x30, 0x64, 0x1b, 0xde, 0xd8, 0xdf, 0xf0, + 0x82, 0x20, 0x4c, 0xbc, 0xc4, 0x0f, 0x83, 0x58, 0x10, 0xd1, 0x6f, 0x40, 0xf3, 0x3e, 0x0b, 0x0e, + 0x19, 0xeb, 0xbb, 0xec, 0x9b, 0x13, 0x16, 0x27, 0xe4, 0x93, 0xb0, 0xe8, 0xb1, 0x6f, 0x31, 0xd6, + 0xef, 0x8e, 0xbd, 0x38, 0x1e, 0x9f, 0x44, 0x5e, 0xcc, 0xda, 0xce, 0x75, 0x67, 0xad, 0xe1, 0xb6, + 0x44, 0xc5, 0x81, 0xc6, 0xc9, 0xab, 0xd0, 0x88, 0x39, 0x29, 0x0b, 0x92, 0x28, 0x1c, 0x9f, 0xb7, + 0x4b, 0x48, 0x57, 0xe7, 0xd8, 0x8e, 0x80, 0xe8, 0x10, 0x16, 0x74, 0x0f, 0xf1, 0x38, 0x0c, 0x62, + 0x46, 0x6e, 0xc3, 0x72, 0xcf, 0x1f, 0x9f, 0xb0, 0xa8, 0x8b, 0x1f, 0x8f, 0x02, 0x36, 0x0a, 0x03, + 0xbf, 0xd7, 0x76, 0xae, 0xcf, 0xac, 0xd5, 0x5c, 0x22, 0xea, 0xf8, 0x17, 0xef, 0xc9, 0x1a, 0x72, + 0x13, 0x16, 0x58, 0x20, 0x70, 0xd6, 0xc7, 0xaf, 0x64, 0x57, 0xcd, 0x14, 0xe6, 0x1f, 0xd0, 0xbf, + 0x72, 0x60, 0xf1, 0x41, 0xe0, 0x27, 0x4f, 0xbc, 0xe1, 0x90, 0x25, 0x6a, 0x4e, 0x37, 0x61, 0xe1, + 0x0c, 0x01, 0x9c, 0xd3, 0x59, 0x18, 0xf5, 0xe5, 0x8c, 0x9a, 0x02, 0x3e, 0x90, 0xe8, 0xd4, 0x91, + 0x95, 0xa6, 0x8e, 0xac, 0x70, 0xb9, 0x66, 0xa6, 0x2c, 0xd7, 0x4d, 0x58, 0x88, 0x58, 0x2f, 0x3c, + 0x65, 0xd1, 0x79, 0xf7, 0xcc, 0x0f, 0xfa, 0xe1, 0x59, 0xbb, 0x7c, 0xdd, 0x59, 0xab, 0xb8, 0x4d, + 0x05, 0x3f, 0x41, 0x94, 0x2e, 0x03, 0x31, 0x67, 0x21, 0xd6, 0x8d, 0x0e, 0x60, 0xe9, 0x71, 0x30, + 0x0c, 0x7b, 0x4f, 0x7f, 0xc2, 0xd9, 0x15, 0x74, 0x5f, 0x2a, 0xec, 0x7e, 0x15, 0x96, 0xed, 0x8e, + 0xe4, 0x00, 0x18, 0xac, 0x6c, 0x9d, 0x78, 0xc1, 0x80, 0xa9, 0x26, 0xd5, 0x10, 0x5e, 0x87, 0x56, + 0x6f, 0x12, 0x45, 0x2c, 0xc8, 0x8d, 0x61, 0x41, 0xe2, 0x7a, 0x10, 0xaf, 0x42, 0x23, 0x60, 0x67, + 0x29, 0x99, 0x64, 0x99, 0x80, 0x9d, 0x29, 0x12, 0xda, 0x86, 0xd5, 0x6c, 0x37, 0x72, 0x00, 0x3f, + 0x76, 0xa0, 0xfc, 0x38, 0x79, 0x16, 0x92, 0x5b, 0x50, 0x4e, 0xce, 0xc7, 0x82, 0x31, 0x9b, 0x77, + 0xc8, 0x2d, 0xe4, 0xf5, 0x5b, 0x9b, 0xfd, 0x7e, 0xc4, 0xe2, 0xf8, 0xd1, 0xf9, 0x98, 0xb9, 0x0d, + 0x4f, 0x14, 0xba, 0x9c, 0x8e, 0xb4, 0x61, 0x4e, 0x96, 0xb1, 0xc3, 0x9a, 0xab, 0x8a, 0xe4, 0x1a, + 0x80, 0x37, 0x0a, 0x27, 0x41, 0xd2, 0x8d, 0xbd, 0x04, 0x77, 0x6e, 0xc6, 0x35, 0x10, 0x72, 0x03, + 0xe6, 0xe3, 0x5e, 0xe4, 0x8f, 0x93, 0xee, 0x78, 0x72, 0xf4, 0x94, 0x9d, 0xe3, 0x8e, 0xd5, 0x5c, + 0x1b, 0x24, 0x9f, 0x84, 0x6a, 0x38, 0x49, 0xc6, 0xa1, 0x1f, 0x24, 0xed, 0xca, 0x75, 0x67, 0xad, + 0x7e, 0x67, 0x41, 0x8e, 0xe9, 0xe1, 0x24, 0x39, 0xe0, 0xb0, 0xab, 0x09, 0x78, 0x93, 0xbd, 0x30, + 0x38, 0xf6, 0xa3, 0x91, 0x90, 0xc5, 0xf6, 0x2c, 0xf6, 0x6a, 0x83, 0xf4, 0x3b, 0x25, 0xa8, 0x3f, + 0x8a, 0xbc, 0x20, 0xf6, 0x7a, 0x1c, 0xe0, 0x53, 0x48, 0x9e, 0x75, 0x4f, 0xbc, 0xf8, 0x04, 0x67, + 0x5d, 0x73, 0x55, 0x91, 0xac, 0xc2, 0xac, 0x18, 0x30, 0xce, 0x6d, 0xc6, 0x95, 0x25, 0xf2, 0x06, + 0x2c, 0x06, 0x93, 0x51, 0xd7, 0xee, 0x6b, 0x06, 0x77, 0x3c, 0x5f, 0xc1, 0x17, 0xe2, 0x88, 0xef, + 0xb9, 0xe8, 0x42, 0xcc, 0xd2, 0x40, 0x08, 0x85, 0x86, 0x2c, 0x31, 0x7f, 0x70, 0x22, 0xa6, 0x59, + 0x71, 0x2d, 0x8c, 0xb7, 0x91, 0xf8, 0x23, 0xd6, 0x8d, 0x13, 0x6f, 0x34, 0x96, 0xd3, 0x32, 0x10, + 0xac, 0x0f, 0x13, 0x6f, 0xd8, 0x3d, 0x66, 0x2c, 0x6e, 0xcf, 0xc9, 0x7a, 0x8d, 0x90, 0xd7, 0xa0, + 0xd9, 0x67, 0x71, 0xd2, 0x95, 0x9b, 0xc3, 0xe2, 0x76, 0x15, 0x25, 0x2f, 0x83, 0x72, 0x0e, 0xb9, + 0xcf, 0x12, 0x63, 0x75, 0x62, 0xc9, 0x89, 0x74, 0x0f, 0x88, 0x01, 0x6f, 0xb3, 0xc4, 0xf3, 0x87, + 0x31, 0x79, 0x0b, 0x1a, 0x89, 0x41, 0x8c, 0x9a, 0xa6, 0xae, 0xd9, 0xc6, 0xf8, 0xc0, 0xb5, 0xe8, + 0xe8, 0x7d, 0xa8, 0xde, 0x63, 0x6c, 0xcf, 0x1f, 0xf9, 0x09, 0x59, 0x85, 0xca, 0xb1, 0xff, 0x8c, + 0x09, 0xc6, 0x9e, 0xd9, 0xbd, 0xe4, 0x8a, 0x22, 0xe9, 0xc0, 0xdc, 0x98, 0x45, 0x3d, 0xa6, 0x96, + 0x7f, 0xf7, 0x92, 0xab, 0x80, 0xbb, 0x73, 0x50, 0x19, 0xf2, 0x8f, 0xe9, 0x3f, 0x96, 0xa0, 0x7e, + 0xc8, 0x02, 0x2d, 0x30, 0x04, 0xca, 0x7c, 0x4a, 0x52, 0x48, 0xf0, 0x7f, 0xf2, 0x0a, 0xd4, 0x71, + 0x9a, 0x71, 0x12, 0xf9, 0xc1, 0x40, 0xf2, 0x29, 0x70, 0xe8, 0x10, 0x11, 0xd2, 0x82, 0x19, 0x6f, + 0xa4, 0x78, 0x94, 0xff, 0xcb, 0x85, 0x69, 0xec, 0x9d, 0x8f, 0xb8, 0xdc, 0xe9, 0x5d, 0x6b, 0xb8, + 0x75, 0x89, 0xed, 0xf2, 0x6d, 0xbb, 0x05, 0x4b, 0x26, 0x89, 0x6a, 0xbd, 0x82, 0xad, 0x2f, 0x1a, + 0x94, 0xb2, 0x93, 0x9b, 0xb0, 0xa0, 0xe8, 0x23, 0x31, 0x58, 0xdc, 0xc7, 0x9a, 0xdb, 0x94, 0xb0, + 0x9a, 0xc2, 0x1a, 0xb4, 0x8e, 0xfd, 0xc0, 0x1b, 0x76, 0x7b, 0xc3, 0xe4, 0xb4, 0xdb, 0x67, 0xc3, + 0xc4, 0xc3, 0x1d, 0xad, 0xb8, 0x4d, 0xc4, 0xb7, 0x86, 0xc9, 0xe9, 0x36, 0x47, 0xc9, 0x1b, 0x50, + 0x3b, 0x66, 0xac, 0x8b, 0x2b, 0xd1, 0xae, 0x5a, 0xd2, 0xa1, 0x56, 0xd7, 0xad, 0x1e, 0xab, 0x75, + 0x5e, 0x83, 0x56, 0x38, 0x49, 0x06, 0xa1, 0x1f, 0x0c, 0xba, 0xbd, 0x13, 0x2f, 0xe8, 0xfa, 0xfd, + 0x76, 0xed, 0xba, 0xb3, 0x56, 0x76, 0x9b, 0x0a, 0xe7, 0xda, 0xe1, 0x41, 0x9f, 0xfe, 0x99, 0x03, + 0x0d, 0xb1, 0xa8, 0xd2, 0xb0, 0xdc, 0x80, 0x79, 0x35, 0x76, 0x16, 0x45, 0x61, 0x24, 0x05, 0xc5, + 0x06, 0xc9, 0x3a, 0xb4, 0x14, 0x30, 0x8e, 0x98, 0x3f, 0xf2, 0x06, 0x4c, 0x6a, 0xa1, 0x1c, 0x4e, + 0xee, 0xa4, 0x2d, 0x46, 0xe1, 0x24, 0x11, 0xaa, 0xbd, 0x7e, 0xa7, 0x21, 0x87, 0xef, 0x72, 0xcc, + 0xb5, 0x49, 0xb8, 0xa0, 0x14, 0x6c, 0x8a, 0x85, 0xd1, 0x1f, 0x38, 0x40, 0xf8, 0xd0, 0x1f, 0x85, + 0xa2, 0x09, 0xb9, 0xa6, 0xd9, 0xfd, 0x74, 0x5e, 0x78, 0x3f, 0x4b, 0xd3, 0xf6, 0x73, 0x0d, 0x66, + 0x71, 0x58, 0x5c, 0xf2, 0x67, 0xb2, 0x43, 0xbf, 0x5b, 0x6a, 0x3b, 0xae, 0xac, 0x27, 0x14, 0x2a, + 0x62, 0x8e, 0xe5, 0x82, 0x39, 0x8a, 0x2a, 0xfa, 0x3d, 0x07, 0x1a, 0x7c, 0xf5, 0x03, 0x36, 0x44, + 0xad, 0x46, 0x6e, 0x03, 0x39, 0x9e, 0x04, 0x7d, 0xbe, 0x59, 0xc9, 0x33, 0xbf, 0xdf, 0x3d, 0x3a, + 0xe7, 0x5d, 0xe1, 0xb8, 0x77, 0x2f, 0xb9, 0x05, 0x75, 0xe4, 0x0d, 0x68, 0x59, 0x68, 0x9c, 0x44, + 0x62, 0xf4, 0xbb, 0x97, 0xdc, 0x5c, 0x0d, 0x5f, 0x4c, 0xae, 0x37, 0x27, 0x49, 0xd7, 0x0f, 0xfa, + 0xec, 0x19, 0xae, 0xff, 0xbc, 0x6b, 0x61, 0x77, 0x9b, 0xd0, 0x30, 0xbf, 0xa3, 0x1f, 0x40, 0x55, + 0x69, 0x5d, 0xd4, 0x38, 0x99, 0x71, 0xb9, 0x06, 0x42, 0x3a, 0x50, 0xb5, 0x47, 0xe1, 0x56, 0x3f, + 0x4e, 0xdf, 0xf4, 0x0b, 0xd0, 0xda, 0xe3, 0xaa, 0x2f, 0xf0, 0x83, 0x81, 0x34, 0x3f, 0x5c, 0x1f, + 0x4b, 0x5b, 0x21, 0xf8, 0x4f, 0x96, 0xb8, 0xd0, 0x9f, 0x84, 0x71, 0x22, 0xfb, 0xc1, 0xff, 0xe9, + 0xbf, 0x38, 0xb0, 0xc0, 0x19, 0xe1, 0x3d, 0x2f, 0x38, 0x57, 0x5c, 0xb0, 0x07, 0x0d, 0xde, 0xd4, + 0xa3, 0x70, 0x53, 0x68, 0x75, 0xa1, 0xad, 0xd6, 0xe4, 0x7e, 0x64, 0xa8, 0x6f, 0x99, 0xa4, 0xdc, + 0xe9, 0x3a, 0x77, 0xad, 0xaf, 0xb9, 0x5a, 0x49, 0xbc, 0x68, 0xc0, 0x12, 0xd4, 0xf7, 0x52, 0xff, + 0x83, 0x80, 0xb6, 0xc2, 0xe0, 0x98, 0x5c, 0x87, 0x46, 0xec, 0x25, 0xdd, 0x31, 0x8b, 0x70, 0x4d, + 0x50, 0x35, 0xcc, 0xb8, 0x10, 0x7b, 0xc9, 0x01, 0x8b, 0xee, 0x9e, 0x27, 0xac, 0xf3, 0x7f, 0x61, + 0x31, 0xd7, 0x0b, 0xd7, 0x46, 0xe9, 0x14, 0xf9, 0xbf, 0x64, 0x19, 0x2a, 0xa7, 0xde, 0x70, 0xc2, + 0xa4, 0x19, 0x12, 0x85, 0x77, 0x4a, 0x6f, 0x3b, 0xf4, 0x35, 0x68, 0xa5, 0xc3, 0x96, 0xc2, 0x4a, + 0xa0, 0xcc, 0x57, 0x5a, 0x36, 0x80, 0xff, 0xd3, 0xef, 0x3a, 0x82, 0x70, 0x2b, 0xf4, 0xb5, 0x4a, + 0xe7, 0x84, 0x5c, 0xf3, 0x2b, 0x42, 0xfe, 0xff, 0x54, 0x93, 0xf7, 0xd3, 0x4f, 0x96, 0x5c, 0x81, + 0x6a, 0xcc, 0x82, 0x7e, 0xd7, 0x1b, 0x0e, 0x51, 0xf3, 0x55, 0xdd, 0x39, 0x5e, 0xde, 0x1c, 0x0e, + 0xe9, 0x4d, 0x58, 0x34, 0x46, 0xf7, 0x9c, 0x79, 0xec, 0x03, 0xd9, 0xf3, 0xe3, 0xe4, 0x71, 0x10, + 0x8f, 0x0d, 0x8d, 0xf9, 0x12, 0xd4, 0x46, 0x7e, 0x80, 0x23, 0x13, 0xac, 0x58, 0x71, 0xab, 0x23, + 0x3f, 0xe0, 0xe3, 0x8a, 0xb1, 0xd2, 0x7b, 0x26, 0x2b, 0x4b, 0xb2, 0xd2, 0x7b, 0x86, 0x95, 0xf4, + 0x6d, 0x58, 0xb2, 0xda, 0x93, 0x5d, 0xbf, 0x0a, 0x95, 0x49, 0xf2, 0x2c, 0x54, 0xf6, 0xac, 0x2e, + 0x39, 0x84, 0x7b, 0x48, 0xae, 0xa8, 0xa1, 0xef, 0xc2, 0xe2, 0x3e, 0x3b, 0x93, 0x9c, 0xa9, 0x06, + 0xf2, 0xda, 0x85, 0xde, 0x13, 0xd6, 0xd3, 0x5b, 0x40, 0xcc, 0x8f, 0x65, 0xaf, 0x86, 0x2f, 0xe5, + 0x58, 0xbe, 0x14, 0x7d, 0x0d, 0xc8, 0xa1, 0x3f, 0x08, 0xde, 0x63, 0x71, 0xec, 0x0d, 0xb4, 0x52, + 0x6b, 0xc1, 0xcc, 0x28, 0x1e, 0x48, 0xd9, 0xe3, 0xff, 0xd2, 0x4f, 0xc1, 0x92, 0x45, 0x27, 0x1b, + 0xbe, 0x0a, 0xb5, 0xd8, 0x1f, 0x04, 0x5e, 0x32, 0x89, 0x98, 0x6c, 0x3a, 0x05, 0xe8, 0x3d, 0x58, + 0xfe, 0x0a, 0x8b, 0xfc, 0xe3, 0xf3, 0x8b, 0x9a, 0xb7, 0xdb, 0x29, 0x65, 0xdb, 0xd9, 0x81, 0x95, + 0x4c, 0x3b, 0xb2, 0x7b, 0xc1, 0xbe, 0x72, 0x27, 0xab, 0xae, 0x28, 0x18, 0xc2, 0x5c, 0x32, 0x85, + 0x99, 0x3e, 0x06, 0xb2, 0x15, 0x06, 0x01, 0xeb, 0x25, 0x07, 0x8c, 0x45, 0xe9, 0xe9, 0x29, 0xe5, + 0xd5, 0xfa, 0x9d, 0xcb, 0x72, 0x65, 0xb3, 0x1a, 0x42, 0x32, 0x31, 0x81, 0xf2, 0x98, 0x45, 0x23, + 0x6c, 0xb8, 0xea, 0xe2, 0xff, 0x74, 0x05, 0x96, 0xac, 0x66, 0xa5, 0xe3, 0xfb, 0x26, 0xac, 0x6c, + 0xfb, 0x71, 0x2f, 0xdf, 0x61, 0x1b, 0xe6, 0xc6, 0x93, 0xa3, 0x6e, 0x2a, 0x89, 0xaa, 0xc8, 0x7d, + 0xa4, 0xec, 0x27, 0xb2, 0xb1, 0x5f, 0x71, 0xa0, 0xbc, 0xfb, 0x68, 0x6f, 0x8b, 0x2b, 0x3f, 0x3f, + 0xe8, 0x85, 0x23, 0x6e, 0x40, 0xc4, 0xa4, 0x75, 0x79, 0xaa, 0x84, 0x5d, 0x85, 0x1a, 0xda, 0x1d, + 0xee, 0xf6, 0xc9, 0x83, 0x4e, 0x0a, 0x70, 0x97, 0x93, 0x3d, 0x1b, 0xfb, 0x11, 0xfa, 0x94, 0xca, + 0x53, 0x2c, 0xa3, 0xde, 0xcc, 0x57, 0xd0, 0xef, 0x56, 0x60, 0x4e, 0x5a, 0x13, 0xec, 0xaf, 0x97, + 0xf8, 0xa7, 0x4c, 0x8e, 0x44, 0x96, 0xb8, 0x4d, 0x8f, 0xd8, 0x28, 0x4c, 0x58, 0xd7, 0xda, 0x06, + 0x1b, 0x44, 0x97, 0x5a, 0x34, 0xd4, 0x15, 0x4e, 0xf8, 0x8c, 0xa0, 0xb2, 0x40, 0xbe, 0x58, 0xca, + 0xa3, 0x28, 0xa3, 0x47, 0xa1, 0x8a, 0x7c, 0x25, 0x7a, 0xde, 0xd8, 0xeb, 0xf9, 0xc9, 0xb9, 0x54, + 0x09, 0xba, 0xcc, 0xdb, 0x1e, 0x86, 0x3d, 0x6f, 0xd8, 0x3d, 0xf2, 0x86, 0x5e, 0xd0, 0x63, 0xca, + 0x5d, 0xb7, 0x40, 0xee, 0xba, 0xca, 0x21, 0x29, 0x32, 0xe1, 0xde, 0x66, 0x50, 0x6e, 0x90, 0x7a, + 0xe1, 0x68, 0xe4, 0x27, 0xdc, 0xe3, 0x45, 0x6f, 0x68, 0xc6, 0x35, 0x10, 0x71, 0x38, 0xc0, 0xd2, + 0x99, 0x58, 0xbd, 0x9a, 0x3a, 0x1c, 0x18, 0x20, 0x6f, 0x85, 0xbb, 0x54, 0x5c, 0x8d, 0x3d, 0x3d, + 0x6b, 0x83, 0x68, 0x25, 0x45, 0xf8, 0x3e, 0x4c, 0x82, 0x98, 0x25, 0xc9, 0x90, 0xf5, 0xf5, 0x80, + 0xea, 0x48, 0x96, 0xaf, 0x20, 0xb7, 0x61, 0x49, 0x38, 0xe1, 0xb1, 0x97, 0x84, 0xf1, 0x89, 0x1f, + 0x77, 0x63, 0xee, 0xce, 0x36, 0x90, 0xbe, 0xa8, 0x8a, 0xbc, 0x0d, 0x97, 0x33, 0x70, 0xc4, 0x7a, + 0xcc, 0x3f, 0x65, 0xfd, 0xf6, 0x3c, 0x7e, 0x35, 0xad, 0x9a, 0x5c, 0x87, 0x3a, 0x3f, 0x7b, 0x4c, + 0xc6, 0x7d, 0x8f, 0x5b, 0xe4, 0x26, 0xee, 0x83, 0x09, 0x91, 0x37, 0x61, 0x7e, 0xcc, 0x84, 0x39, + 0x3f, 0x49, 0x86, 0xbd, 0xb8, 0xbd, 0x60, 0x69, 0x37, 0xce, 0xb9, 0xae, 0x4d, 0xc1, 0x99, 0xb2, + 0x17, 0xa3, 0x13, 0xea, 0x9d, 0xb7, 0x5b, 0xc8, 0x6e, 0x29, 0x80, 0x32, 0x12, 0xf9, 0xa7, 0x5e, + 0xc2, 0xda, 0x8b, 0x42, 0xa1, 0xcb, 0x22, 0xff, 0xce, 0x0f, 0xfc, 0xc4, 0xf7, 0x92, 0x30, 0x6a, + 0x13, 0xac, 0x4b, 0x01, 0xfa, 0xfb, 0x8e, 0x50, 0xbb, 0x92, 0x45, 0xb5, 0xfa, 0x7c, 0x05, 0xea, + 0x82, 0x39, 0xbb, 0x61, 0x30, 0x3c, 0x97, 0xfc, 0x0a, 0x02, 0x7a, 0x18, 0x0c, 0xcf, 0xc9, 0x27, + 0x60, 0xde, 0x0f, 0x4c, 0x12, 0x21, 0xe1, 0x0d, 0x05, 0x22, 0xd1, 0x2b, 0x50, 0x1f, 0x4f, 0x8e, + 0x86, 0x7e, 0x4f, 0x90, 0xcc, 0x88, 0x56, 0x04, 0x84, 0x04, 0xdc, 0x19, 0x14, 0xe3, 0x14, 0x14, + 0x65, 0xa4, 0xa8, 0x4b, 0x8c, 0x93, 0xd0, 0xbb, 0xb0, 0x6c, 0x0f, 0x50, 0xaa, 0xb2, 0x75, 0xa8, + 0x4a, 0xce, 0x8f, 0xdb, 0x75, 0x5c, 0xbd, 0xa6, 0x5c, 0x3d, 0x49, 0xea, 0xea, 0x7a, 0xfa, 0xa7, + 0x65, 0x58, 0x92, 0xe8, 0xd6, 0x30, 0x8c, 0xd9, 0xe1, 0x64, 0x34, 0xf2, 0xa2, 0x02, 0x91, 0x72, + 0x2e, 0x10, 0xa9, 0x92, 0x2d, 0x52, 0x9c, 0xd1, 0x4f, 0x3c, 0x3f, 0x10, 0x9e, 0xac, 0x90, 0x47, + 0x03, 0x21, 0x6b, 0xb0, 0xd0, 0x1b, 0x86, 0xb1, 0xf0, 0xda, 0xcc, 0x43, 0x67, 0x16, 0xce, 0xab, + 0x80, 0x4a, 0x91, 0x0a, 0x30, 0x45, 0x78, 0x36, 0x23, 0xc2, 0x14, 0x1a, 0xbc, 0x51, 0xa6, 0x34, + 0xd2, 0x9c, 0xf0, 0xe4, 0x4c, 0x8c, 0x8f, 0x27, 0x2b, 0x30, 0x42, 0x3a, 0x17, 0x8a, 0xc4, 0x85, + 0x9f, 0x69, 0xb9, 0xc6, 0x33, 0xa8, 0x6b, 0x52, 0x5c, 0xf2, 0x55, 0xe4, 0x1e, 0x80, 0xe8, 0x0b, + 0xcd, 0x2e, 0xa0, 0xd9, 0x7d, 0xcd, 0xde, 0x11, 0x73, 0xed, 0x6f, 0xf1, 0xc2, 0x24, 0x62, 0x68, + 0x8a, 0x8d, 0x2f, 0xe9, 0xaf, 0x3a, 0x50, 0x37, 0xea, 0xc8, 0x0a, 0x2c, 0x6e, 0x3d, 0x7c, 0x78, + 0xb0, 0xe3, 0x6e, 0x3e, 0x7a, 0xf0, 0x95, 0x9d, 0xee, 0xd6, 0xde, 0xc3, 0xc3, 0x9d, 0xd6, 0x25, + 0x0e, 0xef, 0x3d, 0xdc, 0xda, 0xdc, 0xeb, 0xde, 0x7b, 0xe8, 0x6e, 0x29, 0xd8, 0x21, 0xab, 0x40, + 0xdc, 0x9d, 0xf7, 0x1e, 0x3e, 0xda, 0xb1, 0xf0, 0x12, 0x69, 0x41, 0xe3, 0xae, 0xbb, 0xb3, 0xb9, + 0xb5, 0x2b, 0x91, 0x19, 0xb2, 0x0c, 0xad, 0x7b, 0x8f, 0xf7, 0xb7, 0x1f, 0xec, 0xdf, 0xef, 0x6e, + 0x6d, 0xee, 0x6f, 0xed, 0xec, 0xed, 0x6c, 0xb7, 0xca, 0x64, 0x1e, 0x6a, 0x9b, 0x77, 0x37, 0xf7, + 0xb7, 0x1f, 0xee, 0xef, 0x6c, 0xb7, 0x2a, 0xf4, 0x9f, 0x1d, 0x58, 0xc1, 0x51, 0xf7, 0xb3, 0x02, + 0x72, 0x1d, 0xea, 0xbd, 0x30, 0x1c, 0x33, 0xae, 0xed, 0xb5, 0x42, 0x37, 0x21, 0xce, 0xfc, 0x42, + 0x7d, 0x1e, 0x87, 0x51, 0x8f, 0x49, 0xf9, 0x00, 0x84, 0xee, 0x71, 0x84, 0x33, 0xbf, 0xdc, 0x5e, + 0x41, 0x21, 0xc4, 0xa3, 0x2e, 0x30, 0x41, 0xb2, 0x0a, 0xb3, 0x47, 0x11, 0xf3, 0x7a, 0x27, 0x52, + 0x32, 0x64, 0x89, 0xbc, 0x9e, 0x1e, 0x30, 0x7a, 0x7c, 0xf5, 0x87, 0xac, 0x8f, 0x1c, 0x53, 0x75, + 0x17, 0x24, 0xbe, 0x25, 0x61, 0x2e, 0xff, 0xde, 0x91, 0x17, 0xf4, 0xc3, 0x80, 0xf5, 0xa5, 0xb3, + 0x97, 0x02, 0xf4, 0x00, 0x56, 0xb3, 0xf3, 0x93, 0xf2, 0xf5, 0x96, 0x21, 0x5f, 0xc2, 0xf7, 0xea, + 0x4c, 0xdf, 0x4d, 0x43, 0xd6, 0xfe, 0xd5, 0x81, 0x32, 0x37, 0xc5, 0xd3, 0xcd, 0xb6, 0xe9, 0x5d, + 0xcd, 0xe4, 0x22, 0x55, 0x78, 0x66, 0x11, 0xca, 0x59, 0x18, 0x30, 0x03, 0x49, 0xeb, 0x23, 0xd6, + 0x3b, 0xc5, 0x19, 0xeb, 0x7a, 0x8e, 0x70, 0x01, 0xe1, 0xae, 0x2f, 0x7e, 0x2d, 0x05, 0x44, 0x95, + 0x55, 0x1d, 0x7e, 0x39, 0x97, 0xd6, 0xe1, 0x77, 0x6d, 0x98, 0xf3, 0x83, 0xa3, 0x70, 0x12, 0xf4, + 0x51, 0x20, 0xaa, 0xae, 0x2a, 0xf2, 0xe5, 0x1b, 0xa3, 0xa0, 0xfa, 0x23, 0xc5, 0xfe, 0x29, 0x40, + 0x09, 0x3f, 0x1a, 0xc5, 0xe8, 0x7a, 0xe8, 0xf0, 0xcc, 0x5b, 0xb0, 0x68, 0x60, 0xa9, 0x1b, 0x3b, + 0xe6, 0x40, 0xc6, 0x8d, 0x45, 0x9f, 0x45, 0xd4, 0xd0, 0x16, 0x34, 0xef, 0xb3, 0xe4, 0x41, 0x70, + 0x1c, 0xaa, 0x96, 0xfe, 0xa8, 0x0c, 0x0b, 0x1a, 0x92, 0x0d, 0xad, 0xc1, 0x82, 0xdf, 0x67, 0x41, + 0xe2, 0x27, 0xe7, 0x5d, 0xeb, 0x04, 0x96, 0x85, 0xb9, 0xaf, 0xe7, 0x0d, 0x7d, 0x4f, 0x45, 0x03, + 0x45, 0x81, 0xdc, 0x81, 0x65, 0x6e, 0x88, 0x94, 0x6d, 0xd1, 0x5b, 0x2c, 0x0e, 0x7e, 0x85, 0x75, + 0x5c, 0x19, 0x70, 0x5c, 0x6a, 0x7b, 0xfd, 0x89, 0xf0, 0x79, 0x8a, 0xaa, 0xf8, 0xaa, 0x89, 0x96, + 0xf8, 0x94, 0x2b, 0xc2, 0x58, 0x69, 0x20, 0x17, 0x66, 0x9b, 0x15, 0xaa, 0x2a, 0x1b, 0x66, 0x33, + 0x42, 0x75, 0xd5, 0x5c, 0xa8, 0x8e, 0xab, 0xb2, 0xf3, 0xa0, 0xc7, 0xfa, 0xdd, 0x24, 0xec, 0xa2, + 0xca, 0xc5, 0xdd, 0xa9, 0xba, 0x59, 0x98, 0x5c, 0x85, 0xb9, 0x84, 0xc5, 0x49, 0xc0, 0x12, 0xd4, + 0x4a, 0x55, 0x0c, 0x08, 0x28, 0x88, 0x3b, 0xa8, 0x93, 0xc8, 0x8f, 0xdb, 0x0d, 0x0c, 0xc2, 0xe1, + 0xff, 0xe4, 0xd3, 0xb0, 0x72, 0xc4, 0xe2, 0xa4, 0x7b, 0xc2, 0xbc, 0x3e, 0x8b, 0x70, 0xa7, 0x45, + 0xb4, 0x4f, 0xd8, 0xfd, 0xe2, 0x4a, 0xce, 0x43, 0xa7, 0x2c, 0x8a, 0xfd, 0x30, 0x40, 0x8b, 0x5f, + 0x73, 0x55, 0x91, 0xb7, 0xc7, 0x27, 0xaf, 0xed, 0xa5, 0x5e, 0xc1, 0x05, 0x9c, 0x78, 0x71, 0x25, + 0xb9, 0x01, 0xb3, 0x38, 0x81, 0xb8, 0xdd, 0xb2, 0xa2, 0x1a, 0x5b, 0x1c, 0x74, 0x65, 0xdd, 0x17, + 0xcb, 0xd5, 0x7a, 0xab, 0x41, 0xff, 0x0f, 0x54, 0x10, 0xe6, 0x9b, 0x2e, 0x16, 0x43, 0x30, 0x85, + 0x28, 0xf0, 0xa1, 0x05, 0x2c, 0x39, 0x0b, 0xa3, 0xa7, 0x2a, 0x34, 0x2c, 0x8b, 0xf4, 0x5b, 0xe8, + 0xe2, 0xeb, 0x10, 0xe9, 0x63, 0xf4, 0x4f, 0xf8, 0x41, 0x4d, 0x2c, 0x75, 0x7c, 0xe2, 0xc9, 0x53, + 0x47, 0x15, 0x81, 0xc3, 0x13, 0x8f, 0xab, 0x2d, 0x6b, 0xf7, 0xc4, 0x41, 0xae, 0x8e, 0xd8, 0xae, + 0xd8, 0xbc, 0x1b, 0xd0, 0x54, 0xc1, 0xd7, 0xb8, 0x3b, 0x64, 0xc7, 0x89, 0x8a, 0x2b, 0x04, 0x93, + 0x11, 0x9e, 0xf6, 0xf6, 0xd8, 0x71, 0x42, 0xf7, 0x61, 0x51, 0xaa, 0x92, 0x87, 0x63, 0xa6, 0xba, + 0xfe, 0x6c, 0x91, 0x49, 0xae, 0xdf, 0x59, 0xb2, 0x75, 0x8f, 0x08, 0x37, 0xdb, 0x94, 0xd4, 0x05, + 0x62, 0xaa, 0x26, 0xd9, 0xa0, 0xb4, 0x8b, 0x2a, 0x72, 0x22, 0xa7, 0x63, 0x61, 0x7c, 0x7d, 0xe2, + 0x49, 0xaf, 0xa7, 0x42, 0xe7, 0xfc, 0x38, 0x2c, 0x8a, 0xf4, 0x8f, 0x1d, 0x58, 0xc2, 0xd6, 0x94, + 0x53, 0x21, 0xd5, 0xff, 0xdb, 0x1f, 0x63, 0x98, 0x8d, 0x9e, 0x19, 0x4d, 0x5a, 0x86, 0x8a, 0x69, + 0x10, 0x44, 0xe1, 0xe3, 0x1f, 0xea, 0xcb, 0xd9, 0x43, 0x3d, 0xfd, 0x1d, 0x07, 0x16, 0x85, 0x4e, + 0x4e, 0xbc, 0x64, 0x12, 0xcb, 0xe9, 0x7f, 0x0e, 0xe6, 0x85, 0x71, 0x95, 0x52, 0x2d, 0x07, 0xba, + 0xac, 0x15, 0x10, 0xa2, 0x82, 0x78, 0xf7, 0x92, 0x6b, 0x13, 0x93, 0x77, 0xd1, 0xc1, 0x09, 0xba, + 0x88, 0xca, 0xc0, 0xe0, 0x95, 0x02, 0x33, 0xa0, 0xbf, 0x37, 0xc8, 0xef, 0x56, 0x61, 0x56, 0xf8, + 0xbb, 0xf4, 0x3e, 0xcc, 0x5b, 0x1d, 0x59, 0x01, 0x85, 0x86, 0x08, 0x28, 0xe4, 0x42, 0x51, 0xa5, + 0x82, 0x50, 0xd4, 0x9f, 0xcc, 0x00, 0xe1, 0xcc, 0x92, 0xd9, 0x0d, 0xee, 0x70, 0x87, 0x7d, 0xeb, + 0xf8, 0xd4, 0x70, 0x4d, 0x88, 0xdc, 0x02, 0x62, 0x14, 0x55, 0x44, 0x51, 0x58, 0x9f, 0x82, 0x1a, + 0xae, 0x26, 0xa5, 0xf1, 0x96, 0x66, 0x56, 0x1e, 0x14, 0xc5, 0xb2, 0x17, 0xd6, 0x71, 0x03, 0x33, + 0x9e, 0xc4, 0x27, 0x78, 0xc9, 0x22, 0x0f, 0x58, 0xaa, 0x9c, 0xdd, 0xdf, 0xd9, 0x0b, 0xf7, 0x77, + 0x2e, 0x17, 0xb4, 0x31, 0x5c, 0xfc, 0xaa, 0xed, 0xe2, 0xdf, 0x80, 0xf9, 0x11, 0x77, 0x39, 0x93, + 0x61, 0xaf, 0x3b, 0xe2, 0xbd, 0xcb, 0xf3, 0x94, 0x05, 0x92, 0x75, 0x68, 0x49, 0x77, 0x23, 0x3d, + 0x47, 0x00, 0xae, 0x71, 0x0e, 0xe7, 0xfa, 0x3b, 0x0d, 0xe3, 0xd4, 0x71, 0xb0, 0x29, 0xc0, 0x4f, + 0x5e, 0x31, 0xe7, 0x90, 0xee, 0x24, 0x90, 0xf7, 0x2b, 0xac, 0x8f, 0x27, 0xa9, 0xaa, 0x9b, 0xaf, + 0xa0, 0xbf, 0xe5, 0x40, 0x8b, 0xef, 0x99, 0xc5, 0x96, 0xef, 0x00, 0x4a, 0xc5, 0x0b, 0x72, 0xa5, + 0x45, 0x4b, 0xde, 0x86, 0x1a, 0x96, 0xc3, 0x31, 0x0b, 0x24, 0x4f, 0xb6, 0x6d, 0x9e, 0x4c, 0xf5, + 0xc9, 0xee, 0x25, 0x37, 0x25, 0x36, 0x38, 0xf2, 0xef, 0x1d, 0xa8, 0xcb, 0x5e, 0x7e, 0xe2, 0x30, + 0x41, 0xc7, 0xb8, 0x10, 0x13, 0x9c, 0x94, 0xde, 0x7f, 0xad, 0xc1, 0xc2, 0xc8, 0x4b, 0x26, 0x11, + 0xb7, 0xc7, 0x56, 0x88, 0x20, 0x0b, 0x73, 0xe3, 0x8a, 0xaa, 0x33, 0xee, 0x26, 0xfe, 0xb0, 0xab, + 0x6a, 0xe5, 0xd5, 0x53, 0x51, 0x15, 0xd7, 0x20, 0x71, 0xe2, 0x0d, 0x98, 0xb4, 0x9b, 0xa2, 0x40, + 0xdb, 0xb0, 0x2a, 0x27, 0x94, 0x71, 0x55, 0xe9, 0x5f, 0x36, 0xe0, 0x72, 0xae, 0x4a, 0xdf, 0x53, + 0xcb, 0xb3, 0xef, 0xd0, 0x1f, 0x1d, 0x85, 0xda, 0xcf, 0x77, 0xcc, 0x63, 0xb1, 0x55, 0x45, 0x06, + 0xb0, 0xa2, 0x1c, 0x04, 0xbe, 0xa6, 0xa9, 0x31, 0x2b, 0xa1, 0x95, 0x7a, 0xd3, 0xde, 0xc2, 0x6c, + 0x87, 0x0a, 0x37, 0x85, 0xb8, 0xb8, 0x3d, 0x72, 0x02, 0x6d, 0xed, 0x89, 0x48, 0x65, 0x6d, 0x78, + 0x2b, 0xbc, 0xaf, 0x37, 0x2e, 0xe8, 0xcb, 0xf2, 0x6c, 0xdd, 0xa9, 0xad, 0x91, 0x73, 0xb8, 0xa6, + 0xea, 0x50, 0x1b, 0xe7, 0xfb, 0x2b, 0xbf, 0xd0, 0xdc, 0xd0, 0x67, 0xb7, 0x3b, 0xbd, 0xa0, 0x61, + 0xf2, 0x01, 0xac, 0x9e, 0x79, 0x7e, 0xa2, 0x86, 0x65, 0xf8, 0x06, 0x15, 0xec, 0xf2, 0xce, 0x05, + 0x5d, 0x3e, 0x11, 0x1f, 0x5b, 0x26, 0x6a, 0x4a, 0x8b, 0x9d, 0xbf, 0x75, 0xa0, 0x69, 0xb7, 0xc3, + 0xd9, 0x54, 0xca, 0xbe, 0xd2, 0x81, 0xca, 0x9b, 0xcc, 0xc0, 0xf9, 0xa3, 0x72, 0xa9, 0xe8, 0xa8, + 0x6c, 0x1e, 0x50, 0x67, 0x2e, 0x8a, 0x31, 0x95, 0x5f, 0x2c, 0xc6, 0x54, 0x29, 0x8a, 0x31, 0x75, + 0xfe, 0xc3, 0x01, 0x92, 0xe7, 0x25, 0x72, 0x5f, 0x9c, 0xd5, 0x03, 0x36, 0x94, 0x2a, 0xe5, 0x7f, + 0xbf, 0x18, 0x3f, 0xaa, 0xb5, 0x53, 0x5f, 0x73, 0xc1, 0x30, 0xef, 0x8e, 0x4d, 0x67, 0x67, 0xde, + 0x2d, 0xaa, 0xca, 0x44, 0xbd, 0xca, 0x17, 0x47, 0xbd, 0x2a, 0x17, 0x47, 0xbd, 0x66, 0xb3, 0x51, + 0xaf, 0xce, 0x2f, 0x3b, 0xb0, 0x54, 0xb0, 0xe9, 0x3f, 0xbb, 0x89, 0xf3, 0x6d, 0xb2, 0x74, 0x41, + 0x49, 0x6e, 0x93, 0x09, 0x76, 0x7e, 0x1e, 0xe6, 0x2d, 0x46, 0xff, 0xd9, 0xf5, 0x9f, 0xf5, 0xd7, + 0x04, 0x9f, 0x59, 0x58, 0xe7, 0xdf, 0x4a, 0x40, 0xf2, 0xc2, 0xf6, 0x3f, 0x3a, 0x86, 0xfc, 0x3a, + 0xcd, 0x14, 0xac, 0xd3, 0x7f, 0xab, 0x1d, 0x78, 0x03, 0x16, 0x65, 0x52, 0x8b, 0x11, 0xa1, 0x11, + 0x1c, 0x93, 0xaf, 0xe0, 0x1e, 0xab, 0x1d, 0x72, 0xac, 0x5a, 0x09, 0x02, 0x86, 0x31, 0xcc, 0x44, + 0x1e, 0x69, 0x07, 0xda, 0x72, 0x85, 0x76, 0x4e, 0x59, 0x90, 0x1c, 0x4e, 0x8e, 0x44, 0x62, 0x88, + 0x1f, 0x06, 0xf4, 0x07, 0x33, 0xda, 0xe9, 0xc6, 0x4a, 0x69, 0xde, 0x3f, 0x0d, 0x0d, 0x53, 0x99, + 0xcb, 0xed, 0xc8, 0x04, 0xe8, 0xb8, 0x61, 0x37, 0xa9, 0xc8, 0x36, 0x34, 0x51, 0x65, 0xf5, 0xf5, + 0x77, 0x25, 0xfc, 0xee, 0x39, 0x81, 0x87, 0xdd, 0x4b, 0x6e, 0xe6, 0x1b, 0xf2, 0x79, 0x68, 0xda, + 0x47, 0x29, 0xe9, 0x23, 0x14, 0xf9, 0xe6, 0xfc, 0x73, 0x9b, 0x98, 0x6c, 0x42, 0x2b, 0x7b, 0x16, + 0x93, 0xb7, 0xc5, 0x53, 0x1a, 0xc8, 0x91, 0x93, 0xb7, 0xe5, 0xdd, 0x53, 0x05, 0x83, 0x60, 0x37, + 0xec, 0xcf, 0x8c, 0x65, 0xba, 0x25, 0xfe, 0x18, 0xb7, 0x51, 0x5f, 0x07, 0x48, 0x31, 0xd2, 0x82, + 0xc6, 0xc3, 0x83, 0x9d, 0xfd, 0xee, 0xd6, 0xee, 0xe6, 0xfe, 0xfe, 0xce, 0x5e, 0xeb, 0x12, 0x21, + 0xd0, 0xc4, 0xf8, 0xd5, 0xb6, 0xc6, 0x1c, 0x8e, 0x6d, 0x6e, 0x89, 0xd8, 0x98, 0xc4, 0x4a, 0x64, + 0x19, 0x5a, 0x0f, 0xf6, 0x33, 0xe8, 0xcc, 0xdd, 0x9a, 0x96, 0x0f, 0xba, 0x0a, 0xcb, 0x22, 0xf1, + 0xe9, 0xae, 0x60, 0x0f, 0xe5, 0x2b, 0xfc, 0x9e, 0x03, 0x2b, 0x99, 0x8a, 0x34, 0xf1, 0x40, 0xb8, + 0x03, 0xb6, 0x8f, 0x60, 0x83, 0x9c, 0x27, 0xb5, 0xe7, 0x97, 0xd1, 0x20, 0xf9, 0x0a, 0xce, 0xf3, + 0x86, 0xa7, 0x98, 0x91, 0xa4, 0xa2, 0x2a, 0x7a, 0x59, 0xa4, 0x67, 0x05, 0x6c, 0x98, 0x19, 0xf8, + 0xb1, 0x48, 0xa8, 0x32, 0x2b, 0xd2, 0xbb, 0x3c, 0x7b, 0xc8, 0xaa, 0xc8, 0x9d, 0x7c, 0xcb, 0xf5, + 0xb0, 0xc7, 0x5b, 0x58, 0x47, 0x7f, 0xe4, 0x00, 0xf9, 0xf2, 0x84, 0x45, 0xe7, 0x98, 0x33, 0xa0, + 0xc3, 0x81, 0x97, 0xb3, 0xc1, 0xae, 0xd9, 0xf1, 0xe4, 0xe8, 0x4b, 0xec, 0x5c, 0x25, 0xb4, 0x94, + 0xd2, 0x84, 0x96, 0x97, 0x01, 0xf8, 0xe1, 0x58, 0x67, 0x2c, 0xa0, 0x73, 0x1d, 0x4c, 0x46, 0xa2, + 0xc1, 0xc2, 0x9c, 0x93, 0xf2, 0xc5, 0x39, 0x27, 0x95, 0x8b, 0x72, 0x4e, 0xde, 0x80, 0x1a, 0x76, + 0xd9, 0x1d, 0xb3, 0x01, 0x6a, 0x89, 0x94, 0x1a, 0x7b, 0x3e, 0x60, 0x03, 0xb7, 0x1a, 0xc9, 0xff, + 0xe8, 0xbb, 0xb0, 0x64, 0xcd, 0x52, 0x33, 0x81, 0xca, 0xb4, 0x70, 0xf2, 0x99, 0x16, 0x2a, 0xcb, + 0x82, 0x7e, 0xbb, 0x04, 0x33, 0xbb, 0xe1, 0xd8, 0x0c, 0x9c, 0x3b, 0x76, 0xe0, 0x5c, 0x7a, 0x13, + 0x5d, 0xed, 0x2c, 0x48, 0x23, 0x63, 0x81, 0x64, 0x1d, 0x9a, 0xde, 0x28, 0xe9, 0x26, 0x21, 0xf7, + 0x9e, 0xce, 0xbc, 0xa8, 0x2f, 0x38, 0x03, 0x03, 0x38, 0x99, 0x1a, 0xb2, 0x0c, 0x33, 0xda, 0xec, + 0x22, 0x01, 0x2f, 0x72, 0xd7, 0x1d, 0xaf, 0xe4, 0xce, 0x65, 0x10, 0x4a, 0x96, 0x38, 0xe3, 0xd9, + 0xdf, 0x8b, 0x73, 0x93, 0x50, 0x9e, 0x45, 0x55, 0xdc, 0xb3, 0xe1, 0x8b, 0x8d, 0x64, 0x32, 0x7a, + 0xa8, 0xca, 0x66, 0xa4, 0xb3, 0x6a, 0x5f, 0x50, 0xfe, 0xd8, 0x81, 0x0a, 0xae, 0x0d, 0x37, 0x04, + 0x42, 0x52, 0x74, 0xec, 0x1c, 0xd7, 0x64, 0xde, 0xcd, 0xc2, 0x84, 0x5a, 0x09, 0x64, 0x25, 0x3d, + 0x21, 0x33, 0x89, 0xec, 0x3a, 0xd4, 0x44, 0x49, 0x27, 0x4b, 0x21, 0x49, 0x0a, 0x92, 0x6b, 0x50, + 0x3e, 0x09, 0xc7, 0xca, 0x73, 0x05, 0x75, 0xb1, 0x14, 0x8e, 0x5d, 0xc4, 0xd3, 0xf1, 0xf0, 0xf6, + 0xc4, 0xb4, 0x84, 0x3f, 0x92, 0x85, 0xb9, 0x47, 0xa6, 0x9b, 0x35, 0x97, 0x29, 0x83, 0xd2, 0x75, + 0x58, 0xd8, 0x0f, 0xfb, 0xcc, 0x08, 0x60, 0x4e, 0x95, 0x0a, 0xfa, 0x0b, 0x0e, 0x54, 0x15, 0x31, + 0x59, 0x83, 0x32, 0x77, 0x33, 0x33, 0x67, 0x40, 0x7d, 0xa1, 0xcc, 0xe9, 0x5c, 0xa4, 0xe0, 0x76, + 0x19, 0xe3, 0x4a, 0xe9, 0x91, 0x43, 0x45, 0x95, 0x52, 0x8f, 0x5a, 0x0f, 0x37, 0xe3, 0x88, 0x66, + 0x50, 0xfa, 0x7d, 0x07, 0xe6, 0xad, 0x3e, 0xc8, 0x75, 0xa8, 0x0f, 0xbd, 0x38, 0x91, 0x97, 0x74, + 0x72, 0x7b, 0x4c, 0xc8, 0xdc, 0xe8, 0x92, 0x1d, 0xd2, 0xd6, 0xc1, 0xd6, 0x19, 0x33, 0xd8, 0x7a, + 0x1b, 0x6a, 0x69, 0x9a, 0x5f, 0xd9, 0xb2, 0xb7, 0xbc, 0x47, 0x75, 0x55, 0x9e, 0x12, 0x61, 0xfc, + 0x2e, 0x1c, 0x86, 0x91, 0xbc, 0xff, 0x11, 0x05, 0xfa, 0x2e, 0xd4, 0x0d, 0x7a, 0x33, 0x9c, 0xe7, + 0x58, 0xe1, 0x3c, 0x9d, 0x47, 0x52, 0x4a, 0xf3, 0x48, 0xe8, 0xdf, 0x38, 0x30, 0xcf, 0x79, 0xd0, + 0x0f, 0x06, 0x07, 0xe1, 0xd0, 0xef, 0x9d, 0xe3, 0xde, 0x2b, 0x76, 0x93, 0x1a, 0x46, 0xf1, 0xa2, + 0x0d, 0x73, 0xae, 0x57, 0x41, 0x04, 0x29, 0xa2, 0xba, 0xcc, 0x65, 0x98, 0x4b, 0xc0, 0x91, 0x17, + 0x4b, 0xb1, 0x90, 0x0e, 0x90, 0x05, 0x72, 0x49, 0xe3, 0x40, 0xe4, 0x25, 0xac, 0x3b, 0xf2, 0x87, + 0x43, 0x5f, 0xd0, 0x0a, 0xf7, 0xb8, 0xa8, 0x8a, 0xf7, 0xd9, 0xf7, 0x63, 0xef, 0x28, 0xbd, 0xd3, + 0xd0, 0x65, 0xfa, 0xe7, 0x25, 0xa8, 0x2b, 0x3b, 0xda, 0x1f, 0x30, 0x79, 0x01, 0x87, 0x07, 0x10, + 0xad, 0x64, 0x0c, 0x44, 0xd5, 0x5b, 0x47, 0x16, 0x03, 0xc9, 0x6e, 0xf9, 0x4c, 0x7e, 0xcb, 0xaf, + 0x42, 0x8d, 0xb3, 0xde, 0x9b, 0x78, 0x36, 0x12, 0x97, 0x77, 0x29, 0xa0, 0x6a, 0xef, 0x60, 0x6d, + 0x25, 0xad, 0x45, 0xe0, 0xb9, 0xd7, 0x75, 0x6f, 0x43, 0x43, 0x36, 0x83, 0x7b, 0x82, 0x3a, 0x25, + 0x65, 0x7e, 0x6b, 0xbf, 0x5c, 0x8b, 0x52, 0x7d, 0x79, 0x47, 0x7d, 0x59, 0xbd, 0xe8, 0x4b, 0x45, + 0x49, 0xef, 0xeb, 0x5b, 0xd0, 0xfb, 0x91, 0x37, 0x3e, 0x51, 0x52, 0x7a, 0x1b, 0x96, 0xfc, 0xa0, + 0x37, 0x9c, 0xf4, 0x59, 0x77, 0x12, 0x78, 0x41, 0x10, 0x4e, 0x82, 0x1e, 0x53, 0x29, 0x22, 0x45, + 0x55, 0xb4, 0xaf, 0x33, 0xe4, 0xb0, 0x21, 0xb2, 0x0e, 0x15, 0xde, 0x91, 0xb2, 0x0a, 0xc5, 0x22, + 0x2c, 0x48, 0xc8, 0x1a, 0x54, 0x58, 0x7f, 0xc0, 0x54, 0xbc, 0x80, 0x64, 0xbc, 0xa3, 0xfe, 0x80, + 0xb9, 0x82, 0x80, 0x2b, 0x14, 0xcc, 0x82, 0xb4, 0x15, 0x8a, 0x6d, 0x51, 0x66, 0x7b, 0x22, 0x4f, + 0x72, 0x19, 0xc8, 0xbe, 0x90, 0x01, 0xf3, 0x02, 0xe5, 0x97, 0x66, 0xa0, 0x6e, 0xc0, 0x5c, 0x37, + 0x0c, 0xf8, 0x80, 0xbb, 0x7d, 0xdf, 0x1b, 0xb1, 0x84, 0x45, 0x92, 0xef, 0x33, 0x28, 0xa7, 0xf3, + 0x4e, 0x07, 0xdd, 0x70, 0x92, 0x74, 0xfb, 0x6c, 0x10, 0x31, 0xe1, 0x12, 0x70, 0xa3, 0x63, 0xa1, + 0x9c, 0x6e, 0xe4, 0x3d, 0x33, 0xe9, 0x04, 0x07, 0x65, 0x50, 0x75, 0x1d, 0x22, 0xd6, 0xa8, 0x9c, + 0x5e, 0x87, 0x88, 0x15, 0xc9, 0x6a, 0xb5, 0x4a, 0x81, 0x56, 0x7b, 0x0b, 0x56, 0x85, 0xfe, 0x92, + 0x92, 0xde, 0xcd, 0x30, 0xd6, 0x94, 0x5a, 0xb2, 0x0e, 0x2d, 0x3e, 0x66, 0x25, 0x12, 0xb1, 0xff, + 0x2d, 0x11, 0x5a, 0x74, 0xdc, 0x1c, 0xce, 0x69, 0x31, 0xc6, 0x67, 0xd2, 0x8a, 0xeb, 0xe1, 0x1c, + 0x8e, 0xb4, 0xde, 0x33, 0x9b, 0xb6, 0x26, 0x69, 0x33, 0x38, 0x9d, 0x87, 0xfa, 0x61, 0x12, 0x8e, + 0xd5, 0xa6, 0x34, 0xa1, 0x21, 0x8a, 0x32, 0x55, 0xe7, 0x25, 0xb8, 0x82, 0x5c, 0xf4, 0x28, 0x1c, + 0x87, 0xc3, 0x70, 0x70, 0x6e, 0x9d, 0x2f, 0xfe, 0xce, 0x81, 0x25, 0xab, 0x36, 0x3d, 0x60, 0x60, + 0x68, 0x42, 0xe5, 0x58, 0x08, 0xc6, 0x5b, 0x34, 0x94, 0xab, 0x20, 0x14, 0x51, 0xe0, 0xc7, 0x32, + 0xed, 0x62, 0x13, 0x16, 0xd4, 0xc8, 0xd4, 0x87, 0x82, 0x0b, 0xdb, 0x79, 0x2e, 0x94, 0xdf, 0x37, + 0xe5, 0x07, 0xaa, 0x89, 0xcf, 0xcb, 0x6b, 0x76, 0x71, 0xde, 0x50, 0x91, 0x28, 0x7d, 0x42, 0x31, + 0xcf, 0xa3, 0x6a, 0x04, 0x3d, 0x0d, 0xc6, 0xf4, 0xd7, 0x1c, 0x80, 0x74, 0x74, 0x78, 0x39, 0xab, + 0x0d, 0x84, 0x78, 0x1b, 0x62, 0x18, 0x83, 0x57, 0xa1, 0xa1, 0x2f, 0xf5, 0x52, 0x9b, 0x53, 0x57, + 0x18, 0x77, 0x2f, 0x6f, 0xc2, 0xc2, 0x60, 0x18, 0x1e, 0xa1, 0xc1, 0xc6, 0xdc, 0xaf, 0x58, 0x26, + 0x2c, 0x35, 0x05, 0x7c, 0x4f, 0xa2, 0xa9, 0x81, 0x2a, 0x1b, 0x06, 0x8a, 0xfe, 0x7a, 0x49, 0xdf, + 0xc1, 0xa4, 0x73, 0x9e, 0x2a, 0x65, 0xe4, 0x4e, 0x4e, 0x9d, 0x4e, 0xb9, 0xf2, 0xc0, 0x98, 0xeb, + 0xc1, 0x85, 0x21, 0xa1, 0x77, 0xa1, 0x19, 0x09, 0x7d, 0xa5, 0x94, 0x59, 0xf9, 0x39, 0xca, 0x6c, + 0x3e, 0xb2, 0xac, 0xd8, 0xeb, 0xd0, 0xf2, 0xfa, 0xa7, 0x2c, 0x4a, 0x7c, 0x3c, 0x94, 0xa3, 0x0b, + 0x21, 0x54, 0xf0, 0x82, 0x81, 0xa3, 0x65, 0xbf, 0x09, 0x0b, 0x32, 0x49, 0x4c, 0x53, 0xca, 0x84, + 0xef, 0x14, 0xe6, 0x84, 0xf4, 0x0f, 0xd4, 0x75, 0x8f, 0xbd, 0x87, 0xd3, 0x57, 0xc4, 0x9c, 0x5d, + 0x29, 0x33, 0xbb, 0x4f, 0xc8, 0xab, 0x97, 0xbe, 0x3a, 0xf9, 0xcf, 0x18, 0x29, 0x19, 0x7d, 0x79, + 0x55, 0x66, 0x2f, 0x69, 0xf9, 0x45, 0x96, 0x94, 0x7e, 0x0e, 0x66, 0x77, 0xc3, 0xf1, 0x01, 0x1b, + 0xa0, 0x27, 0xc0, 0xc5, 0x40, 0xe7, 0x66, 0xaa, 0xe2, 0xf4, 0xa4, 0x15, 0xfa, 0x19, 0xa8, 0x2a, + 0x87, 0x9f, 0xbc, 0x0e, 0xd5, 0x93, 0x70, 0xcc, 0x8f, 0x04, 0x4a, 0x84, 0xe6, 0x53, 0x4f, 0x11, + 0x4f, 0x04, 0xaa, 0x9a, 0xfe, 0xd0, 0x81, 0xb9, 0xdd, 0x70, 0xbc, 0x2b, 0x33, 0x62, 0x3e, 0x6e, + 0xb7, 0xc5, 0xee, 0xc2, 0x7c, 0xd6, 0x5d, 0xf8, 0x7f, 0xf0, 0x12, 0x06, 0xbb, 0xa2, 0x70, 0x1c, + 0x46, 0x5c, 0x03, 0x78, 0x43, 0xe1, 0x1b, 0x84, 0x41, 0x72, 0xa2, 0x74, 0xe7, 0xf3, 0x48, 0xf0, + 0x04, 0xca, 0x4f, 0x4e, 0xc2, 0xd3, 0x97, 0xee, 0x8d, 0x50, 0xa9, 0xf9, 0x0a, 0xfa, 0x59, 0xa8, + 0xe1, 0x62, 0xe0, 0xb4, 0xde, 0x80, 0x1a, 0x9f, 0xee, 0x89, 0x1f, 0x24, 0x6a, 0x39, 0x9a, 0xe9, + 0x72, 0xec, 0xe2, 0x2e, 0x68, 0x02, 0xfa, 0xed, 0x59, 0x98, 0x7b, 0x10, 0x9c, 0x86, 0x7e, 0x0f, + 0xef, 0xb3, 0x46, 0x6c, 0x14, 0xaa, 0x04, 0x59, 0xfe, 0x3f, 0xb9, 0x0a, 0x73, 0x98, 0x11, 0x36, + 0x16, 0x92, 0xd2, 0x10, 0xf7, 0xce, 0x12, 0xe2, 0x9e, 0x49, 0x94, 0xe6, 0xe6, 0x0b, 0x99, 0x35, + 0x10, 0x7e, 0x72, 0x89, 0xcc, 0xdc, 0x7a, 0x59, 0x4a, 0x13, 0x90, 0x2b, 0x46, 0x02, 0x32, 0xef, + 0x4b, 0x66, 0xf0, 0x88, 0x14, 0x0f, 0xd1, 0x97, 0x84, 0xf0, 0xb4, 0x15, 0x31, 0x11, 0xac, 0x44, + 0x3f, 0x67, 0x4e, 0x9e, 0xb6, 0x4c, 0x90, 0xfb, 0x42, 0xe2, 0x03, 0x41, 0x23, 0x34, 0xbf, 0x09, + 0x71, 0xbf, 0x31, 0xfb, 0x6e, 0xa2, 0x26, 0x04, 0x2e, 0x03, 0x73, 0xf3, 0xd0, 0x67, 0x5a, 0x8b, + 0x8b, 0x79, 0x80, 0x78, 0x7f, 0x90, 0xc5, 0x8d, 0x33, 0x9a, 0x48, 0xde, 0x53, 0x67, 0x34, 0xce, + 0x30, 0xde, 0x70, 0x78, 0xe4, 0xf5, 0x9e, 0xe2, 0xb3, 0x18, 0xbc, 0x61, 0xaa, 0xb9, 0x36, 0x88, + 0x79, 0x38, 0xe9, 0xae, 0xe2, 0x0d, 0x7d, 0xd9, 0x35, 0x21, 0x72, 0x07, 0xea, 0xe2, 0xe0, 0x2b, + 0xf6, 0xb5, 0x89, 0xfb, 0xda, 0x32, 0x0f, 0xae, 0xb8, 0xb3, 0x26, 0x91, 0x79, 0xd7, 0xb6, 0x90, + 0x4b, 0xa7, 0xf3, 0xfa, 0x7d, 0x79, 0x45, 0xd9, 0xc2, 0xde, 0x52, 0x80, 0x9b, 0x72, 0xb9, 0x60, + 0x82, 0x60, 0x11, 0x09, 0x2c, 0x8c, 0x5c, 0x83, 0x2a, 0x3f, 0x33, 0x8d, 0x3d, 0xbf, 0x8f, 0xf9, + 0x78, 0xe2, 0xe8, 0xa6, 0x31, 0xde, 0x86, 0xfa, 0x1f, 0xaf, 0x12, 0x97, 0x70, 0x55, 0x2c, 0x8c, + 0xaf, 0x8d, 0x2e, 0xa3, 0x30, 0x2d, 0x8b, 0x1d, 0xb5, 0x40, 0xf2, 0x26, 0x5e, 0x14, 0x25, 0xac, + 0xbd, 0x82, 0x81, 0xa8, 0x97, 0xe4, 0x9c, 0x25, 0xd3, 0xaa, 0xbf, 0x87, 0x9c, 0xc4, 0x15, 0x94, + 0xf4, 0x53, 0xd0, 0x30, 0x61, 0x52, 0x85, 0xf2, 0xc3, 0x83, 0x9d, 0xfd, 0xd6, 0x25, 0x52, 0x87, + 0xb9, 0xc3, 0x9d, 0x47, 0x8f, 0xf6, 0x76, 0xb6, 0x5b, 0x0e, 0x69, 0x40, 0x55, 0x27, 0x4d, 0x95, + 0x68, 0x02, 0x64, 0xb3, 0xdf, 0x97, 0xdf, 0xe9, 0x58, 0x41, 0xca, 0xc1, 0x8e, 0xc5, 0xc1, 0x05, + 0x5c, 0x54, 0x2a, 0xe6, 0xa2, 0xe7, 0xae, 0x35, 0xdd, 0x81, 0xfa, 0x81, 0xf1, 0x68, 0x04, 0x05, + 0x4a, 0x3d, 0x17, 0x91, 0x82, 0x68, 0x20, 0xc6, 0x70, 0x4a, 0xe6, 0x70, 0xe8, 0x1f, 0x3a, 0x22, + 0x91, 0x5d, 0x0f, 0x5f, 0xf4, 0x4d, 0xa1, 0xa1, 0xe3, 0x3f, 0x69, 0x06, 0xa4, 0x85, 0x71, 0x1a, + 0x1c, 0x4a, 0x37, 0x3c, 0x3e, 0x8e, 0x99, 0xca, 0x57, 0xb2, 0x30, 0x2e, 0x09, 0xdc, 0x91, 0xe3, + 0x4e, 0x91, 0x2f, 0x7a, 0x88, 0x65, 0xde, 0x52, 0x0e, 0xe7, 0xc6, 0x24, 0x62, 0xa7, 0x2c, 0x8a, + 0x75, 0xa6, 0x96, 0x2e, 0xeb, 0x44, 0xcd, 0xec, 0x2a, 0xaf, 0x43, 0x55, 0xb7, 0x6b, 0xab, 0x2c, + 0x45, 0xa9, 0xeb, 0xb9, 0x6a, 0xc4, 0xa3, 0x8d, 0x35, 0x68, 0xa1, 0xa6, 0xf3, 0x15, 0xe4, 0x16, + 0x90, 0x63, 0x3f, 0xca, 0x92, 0xcf, 0x20, 0x79, 0x41, 0x0d, 0x7d, 0x02, 0x4b, 0x8a, 0x75, 0x0c, + 0x0f, 0xce, 0xde, 0x44, 0xe7, 0x22, 0x81, 0x29, 0xe5, 0x05, 0x86, 0xfe, 0xa7, 0x03, 0x73, 0x72, + 0xa7, 0x73, 0x0f, 0x8f, 0xc4, 0x3e, 0x5b, 0x18, 0x69, 0x5b, 0x6f, 0x34, 0x50, 0xba, 0xa4, 0x9a, + 0xcc, 0x29, 0xc2, 0x99, 0x22, 0x45, 0x48, 0xa0, 0x3c, 0xf6, 0x92, 0x13, 0x3c, 0xb0, 0xd7, 0x5c, + 0xfc, 0x9f, 0xb4, 0x44, 0x78, 0x49, 0x28, 0x5d, 0x0c, 0x2d, 0x15, 0x3d, 0xb1, 0x12, 0x4e, 0x45, + 0xfe, 0x89, 0xd5, 0x55, 0xa8, 0xe1, 0x00, 0xba, 0x69, 0xf4, 0x28, 0x05, 0x38, 0xe7, 0x8a, 0x02, + 0x4a, 0xb2, 0x4c, 0x97, 0x4e, 0x11, 0xba, 0x22, 0x76, 0x5e, 0x2e, 0x81, 0xbe, 0xd6, 0x95, 0x89, + 0xb1, 0x29, 0x9c, 0x72, 0x84, 0x1c, 0x40, 0x96, 0x23, 0x24, 0xa9, 0xab, 0xeb, 0x69, 0x07, 0xda, + 0xdb, 0x6c, 0xc8, 0x12, 0xb6, 0x39, 0x1c, 0x66, 0xdb, 0x7f, 0x09, 0xae, 0x14, 0xd4, 0x49, 0xa7, + 0xfd, 0xcb, 0xb0, 0xb2, 0x29, 0x92, 0x08, 0x7f, 0x56, 0x89, 0x31, 0xb4, 0x0d, 0xab, 0xd9, 0x26, + 0x65, 0x67, 0xf7, 0x60, 0x71, 0x9b, 0x1d, 0x4d, 0x06, 0x7b, 0xec, 0x34, 0xed, 0x88, 0x40, 0x39, + 0x3e, 0x09, 0xcf, 0xa4, 0x60, 0xe2, 0xff, 0xe4, 0x65, 0x80, 0x21, 0xa7, 0xe9, 0xc6, 0x63, 0xd6, + 0x53, 0xcf, 0x22, 0x10, 0x39, 0x1c, 0xb3, 0x1e, 0x7d, 0x0b, 0x88, 0xd9, 0x8e, 0x5c, 0x2f, 0x6e, + 0xf7, 0x26, 0x47, 0xdd, 0xf8, 0x3c, 0x4e, 0xd8, 0x48, 0xbd, 0xf7, 0x30, 0x21, 0x7a, 0x13, 0x1a, + 0x07, 0xde, 0xb9, 0xcb, 0xbe, 0x29, 0xdf, 0x9b, 0x5d, 0x86, 0xb9, 0xb1, 0x77, 0xce, 0xd5, 0x94, + 0x0e, 0x6b, 0x61, 0x35, 0xfd, 0xf7, 0x12, 0xcc, 0x0a, 0x4a, 0xde, 0x6a, 0x9f, 0xc5, 0x89, 0x1f, + 0x20, 0x63, 0xa9, 0x56, 0x0d, 0x28, 0xc7, 0xca, 0xa5, 0x02, 0x56, 0x96, 0x47, 0x43, 0x95, 0x62, + 0x2e, 0xf9, 0xd5, 0xc2, 0x38, 0x73, 0xa5, 0x19, 0x6a, 0x22, 0xae, 0x92, 0x02, 0x99, 0x08, 0x68, + 0x6a, 0x5d, 0xc5, 0xf8, 0x94, 0x94, 0x4a, 0xce, 0x35, 0xa1, 0x42, 0x1b, 0x3e, 0x27, 0x18, 0x3c, + 0x67, 0xc3, 0x73, 0xb6, 0xba, 0xfa, 0x02, 0xb6, 0x5a, 0x9c, 0x17, 0x9f, 0x67, 0xab, 0xe1, 0x05, + 0x6c, 0x35, 0x25, 0xd0, 0xba, 0xc7, 0x98, 0xcb, 0xb8, 0x37, 0xa8, 0x78, 0xf7, 0x3b, 0x0e, 0xb4, + 0x24, 0x17, 0xe9, 0x3a, 0xf2, 0xaa, 0xe5, 0x6a, 0x17, 0xa6, 0x7a, 0xdf, 0x80, 0x79, 0xf4, 0x45, + 0x75, 0xa8, 0x57, 0xc6, 0xa5, 0x2d, 0x90, 0xcf, 0x43, 0xdd, 0xc8, 0x8e, 0xfc, 0xa1, 0xdc, 0x14, + 0x13, 0x52, 0xd1, 0xe2, 0xc8, 0x93, 0x99, 0x5a, 0x8e, 0xab, 0xcb, 0xf4, 0x2f, 0x1c, 0x58, 0x34, + 0x06, 0x2c, 0xb9, 0xf0, 0x5d, 0x50, 0xd2, 0x20, 0xe2, 0xbe, 0x42, 0x72, 0x2f, 0xdb, 0x62, 0x93, + 0x7e, 0x66, 0x11, 0xe3, 0x66, 0x7a, 0xe7, 0x38, 0xc0, 0x78, 0x32, 0x92, 0x4a, 0xd4, 0x84, 0x38, + 0x23, 0x9d, 0x31, 0xf6, 0x54, 0x93, 0x08, 0x35, 0x6e, 0x61, 0x98, 0x46, 0xc4, 0x7d, 0x68, 0x4d, + 0x24, 0xec, 0x99, 0x0d, 0xd2, 0x7f, 0x72, 0x60, 0x49, 0x9c, 0xc0, 0xe4, 0xf9, 0x56, 0xbf, 0xd2, + 0x99, 0x15, 0x47, 0x4e, 0x21, 0x91, 0xbb, 0x97, 0x5c, 0x59, 0x26, 0x9f, 0x79, 0xc1, 0x53, 0xa3, + 0x4e, 0x1f, 0x9b, 0xb2, 0x17, 0x33, 0x45, 0x7b, 0xf1, 0x9c, 0x95, 0x2e, 0x8a, 0x73, 0x56, 0x0a, + 0xe3, 0x9c, 0x77, 0xe7, 0xa0, 0x12, 0xf7, 0xc2, 0x31, 0xa3, 0xab, 0xb0, 0x6c, 0x4f, 0x4e, 0xaa, + 0xa0, 0xef, 0x39, 0xd0, 0xbe, 0x27, 0xee, 0x03, 0xfc, 0x60, 0xb0, 0xeb, 0xc7, 0x49, 0x18, 0xe9, + 0xc7, 0x8c, 0xd7, 0x00, 0xe2, 0xc4, 0x8b, 0x12, 0x91, 0x24, 0x2c, 0xa3, 0x90, 0x29, 0xc2, 0xc7, + 0xc8, 0x82, 0xbe, 0xa8, 0x15, 0x7b, 0xa3, 0xcb, 0x39, 0x1f, 0x42, 0x9e, 0x11, 0x2d, 0x4b, 0xfc, + 0x9a, 0x48, 0xa7, 0xe4, 0xbe, 0x02, 0x3b, 0x45, 0xbd, 0x2e, 0xce, 0x41, 0x19, 0x94, 0xfe, 0x83, + 0x03, 0x0b, 0xe9, 0x20, 0xf1, 0xa2, 0xd1, 0xd6, 0x0e, 0xd2, 0xfc, 0xa6, 0xda, 0x41, 0xc5, 0x47, + 0x7d, 0x6e, 0x8f, 0xe5, 0xd8, 0x0c, 0x04, 0x25, 0x56, 0x96, 0xc2, 0x89, 0x72, 0x70, 0x4c, 0x48, + 0x24, 0x47, 0x71, 0x4f, 0x40, 0x7a, 0x35, 0xb2, 0x84, 0x39, 0xde, 0xa3, 0x04, 0xbf, 0x9a, 0x15, + 0x07, 0x41, 0x59, 0x54, 0xa6, 0x74, 0x0e, 0x51, 0x34, 0xa5, 0xe6, 0xdd, 0x4a, 0x55, 0xac, 0x8f, + 0x2a, 0xd3, 0xdf, 0x70, 0xe0, 0x4a, 0xc1, 0xc2, 0x4b, 0xa9, 0xd9, 0x86, 0xc5, 0x63, 0x5d, 0xa9, + 0x16, 0x47, 0x88, 0xce, 0xaa, 0xba, 0x0a, 0xb3, 0x17, 0xc4, 0xcd, 0x7f, 0xa0, 0xfd, 0x22, 0xb1, + 0xdc, 0x56, 0xfa, 0x61, 0xbe, 0x62, 0xfd, 0x0b, 0x50, 0x37, 0x9e, 0x11, 0x92, 0xcb, 0xb0, 0xf4, + 0xe4, 0xc1, 0xa3, 0xfd, 0x9d, 0xc3, 0xc3, 0xee, 0xc1, 0xe3, 0xbb, 0x5f, 0xda, 0xf9, 0x6a, 0x77, + 0x77, 0xf3, 0x70, 0xb7, 0x75, 0x89, 0xac, 0x02, 0xd9, 0xdf, 0x39, 0x7c, 0xb4, 0xb3, 0x6d, 0xe1, + 0xce, 0x9d, 0xdf, 0x9c, 0x81, 0xa6, 0xb8, 0x62, 0x15, 0x3f, 0x40, 0xc1, 0x22, 0xf2, 0x1e, 0xcc, + 0xc9, 0x1f, 0x10, 0x21, 0x2b, 0x72, 0xd8, 0xf6, 0x4f, 0x96, 0x74, 0x56, 0xb3, 0xb0, 0xe4, 0xcb, + 0xa5, 0x5f, 0xfc, 0xe1, 0x8f, 0x7e, 0xbb, 0x34, 0x4f, 0xea, 0x1b, 0xa7, 0x6f, 0x6e, 0x0c, 0x58, + 0x10, 0xf3, 0x36, 0xbe, 0x0e, 0x90, 0xfe, 0xb4, 0x06, 0x69, 0x6b, 0x7f, 0x30, 0xf3, 0x9b, 0x21, + 0x9d, 0x2b, 0x05, 0x35, 0xb2, 0xdd, 0x2b, 0xd8, 0xee, 0x12, 0x6d, 0xf2, 0x76, 0xfd, 0xc0, 0x4f, + 0xc4, 0xef, 0x6c, 0xbc, 0xe3, 0xac, 0x93, 0x3e, 0x34, 0xcc, 0x5f, 0xce, 0x20, 0x2a, 0xf6, 0x55, + 0xf0, 0xbb, 0x1d, 0x9d, 0x97, 0x0a, 0xeb, 0x54, 0xe0, 0x0f, 0xfb, 0x58, 0xa1, 0x2d, 0xde, 0xc7, + 0x04, 0x29, 0xd2, 0x5e, 0x86, 0xd0, 0xb4, 0x7f, 0x20, 0x83, 0x5c, 0x35, 0x54, 0x46, 0xee, 0xe7, + 0x39, 0x3a, 0x2f, 0x4f, 0xa9, 0x95, 0x7d, 0xbd, 0x8c, 0x7d, 0x5d, 0xa6, 0x84, 0xf7, 0xd5, 0x43, + 0x1a, 0xf5, 0xf3, 0x1c, 0xef, 0x38, 0xeb, 0x77, 0xfe, 0xfa, 0x3a, 0xd4, 0x74, 0xb4, 0x9a, 0x7c, + 0x00, 0xf3, 0xd6, 0x1d, 0x38, 0x51, 0xd3, 0x28, 0xba, 0x32, 0xef, 0x5c, 0x2d, 0xae, 0x94, 0x1d, + 0x5f, 0xc3, 0x8e, 0xdb, 0x64, 0x95, 0x77, 0x2c, 0x2f, 0x91, 0x37, 0x30, 0x9b, 0x43, 0xa4, 0x66, + 0x3f, 0x15, 0xf3, 0x4c, 0xef, 0xad, 0xad, 0x79, 0xe6, 0xee, 0xb9, 0xad, 0x79, 0xe6, 0x2f, 0xbb, + 0xe9, 0x55, 0xec, 0x6e, 0x95, 0x2c, 0x9b, 0xdd, 0xe9, 0x28, 0x32, 0xc3, 0xf7, 0x04, 0xe6, 0x6f, + 0x4a, 0x90, 0x97, 0x35, 0x63, 0x15, 0xfd, 0xd6, 0x84, 0x66, 0x91, 0xfc, 0x0f, 0x4e, 0xd0, 0x36, + 0x76, 0x45, 0x08, 0x6e, 0x9f, 0xf9, 0x93, 0x12, 0xe4, 0x6b, 0x50, 0xd3, 0x6f, 0x88, 0xc9, 0x65, + 0xe3, 0x4d, 0xb7, 0xf9, 0xe6, 0xb9, 0xd3, 0xce, 0x57, 0x14, 0x31, 0x86, 0xd9, 0x32, 0x67, 0x8c, + 0x27, 0x50, 0x37, 0xde, 0x09, 0x93, 0x2b, 0xfa, 0xae, 0x21, 0xfb, 0x16, 0xb9, 0xd3, 0x29, 0xaa, + 0x92, 0x5d, 0x2c, 0x62, 0x17, 0x75, 0x52, 0x43, 0xde, 0x4b, 0x9e, 0x85, 0x31, 0xd9, 0x83, 0x15, + 0x79, 0x70, 0x39, 0x62, 0x1f, 0x67, 0x89, 0x0a, 0x7e, 0x62, 0xe3, 0xb6, 0x43, 0xde, 0x85, 0xaa, + 0x7a, 0x0e, 0x4e, 0x56, 0x8b, 0x9f, 0xb5, 0x77, 0x2e, 0xe7, 0x70, 0xa9, 0xd6, 0xbe, 0x0a, 0x90, + 0x3e, 0x4a, 0xd6, 0x02, 0x9c, 0x7b, 0xe4, 0xac, 0x77, 0x27, 0xff, 0x82, 0x99, 0xae, 0xe2, 0x04, + 0x5b, 0x04, 0x05, 0x38, 0x60, 0x67, 0xea, 0x85, 0xcd, 0x37, 0xa0, 0x6e, 0xbc, 0x4b, 0xd6, 0xcb, + 0x97, 0x7f, 0xd3, 0xac, 0x97, 0xaf, 0xe0, 0x19, 0x33, 0xed, 0x60, 0xeb, 0xcb, 0x74, 0x81, 0xb7, + 0x1e, 0xfb, 0x83, 0x60, 0x24, 0x08, 0xf8, 0x06, 0x9d, 0xc0, 0xbc, 0xf5, 0xf8, 0x58, 0x4b, 0x4f, + 0xd1, 0xd3, 0x66, 0x2d, 0x3d, 0x85, 0xef, 0x95, 0x15, 0x3b, 0xd3, 0x45, 0xde, 0xcf, 0x29, 0x92, + 0x18, 0x3d, 0xbd, 0x0f, 0x75, 0xe3, 0x21, 0xb1, 0x9e, 0x4b, 0xfe, 0xcd, 0xb2, 0x9e, 0x4b, 0xd1, + 0xbb, 0xe3, 0x65, 0xec, 0xa3, 0x49, 0x91, 0x15, 0xf0, 0x81, 0x0a, 0x6f, 0xfb, 0x03, 0x68, 0xda, + 0x4f, 0x8b, 0xb5, 0x5c, 0x16, 0x3e, 0x52, 0xd6, 0x72, 0x39, 0xe5, 0x3d, 0xb2, 0x64, 0xe9, 0xf5, + 0x25, 0xdd, 0xc9, 0xc6, 0x87, 0xf2, 0xee, 0xf8, 0x23, 0xf2, 0x65, 0xae, 0x7c, 0xe4, 0x8b, 0x21, + 0x72, 0xd9, 0xe0, 0x5a, 0xf3, 0x5d, 0x91, 0x96, 0x97, 0xdc, 0xe3, 0x22, 0x9b, 0x99, 0xc5, 0x13, + 0x1b, 0xb4, 0x28, 0xf8, 0x72, 0xc8, 0xb0, 0x28, 0xe6, 0xe3, 0x22, 0xc3, 0xa2, 0x58, 0x0f, 0x8c, + 0xb2, 0x16, 0x25, 0xf1, 0x79, 0x1b, 0x01, 0x2c, 0x64, 0x72, 0xe8, 0xb4, 0x54, 0x14, 0x27, 0x1d, + 0x77, 0xae, 0x3d, 0x3f, 0xf5, 0xce, 0x56, 0x54, 0x4a, 0x41, 0x6d, 0xa8, 0x14, 0xef, 0x9f, 0x83, + 0x86, 0xf9, 0xe8, 0x93, 0x98, 0xa2, 0x9c, 0xed, 0xe9, 0xa5, 0xc2, 0x3a, 0x7b, 0x73, 0x49, 0xc3, + 0xec, 0x86, 0x7c, 0x05, 0x56, 0xb5, 0xa8, 0x9b, 0x69, 0x59, 0x31, 0x79, 0xa5, 0x20, 0x59, 0xcb, + 0x0c, 0x67, 0x74, 0xae, 0x4c, 0xcd, 0xe6, 0xba, 0xed, 0x70, 0xa6, 0xb1, 0x5f, 0xd3, 0xa5, 0xca, + 0xbc, 0xe8, 0x11, 0x61, 0xaa, 0xcc, 0x0b, 0x9f, 0xe0, 0x29, 0xa6, 0x21, 0x4b, 0xd6, 0x1a, 0x89, + 0xeb, 0x03, 0xf2, 0x3e, 0x2c, 0x18, 0x89, 0xaf, 0x87, 0xe7, 0x41, 0x4f, 0x0b, 0x40, 0xfe, 0x85, + 0x44, 0xa7, 0xc8, 0xdf, 0xa6, 0x97, 0xb1, 0xfd, 0x45, 0x6a, 0x2d, 0x0e, 0x67, 0xfe, 0x2d, 0xa8, + 0x9b, 0x49, 0xb5, 0xcf, 0x69, 0xf7, 0xb2, 0x51, 0x65, 0x26, 0xf8, 0xdf, 0x76, 0xc8, 0xef, 0x3a, + 0xd0, 0xb0, 0x52, 0x54, 0xad, 0x4b, 0xb2, 0x4c, 0x3b, 0x6d, 0xb3, 0xce, 0x6c, 0x88, 0xba, 0x38, + 0xc8, 0xbd, 0xf5, 0x2f, 0x5a, 0x8b, 0xf0, 0xa1, 0x75, 0x6e, 0xbb, 0x95, 0xfd, 0x4d, 0x95, 0x8f, + 0xb2, 0x04, 0xe6, 0x2b, 0x92, 0x8f, 0x6e, 0x3b, 0xe4, 0xfb, 0x0e, 0x34, 0xed, 0x68, 0x83, 0xde, + 0xaa, 0xc2, 0xb8, 0x86, 0xde, 0xaa, 0x29, 0x21, 0x8a, 0xf7, 0x71, 0x94, 0x8f, 0xd6, 0x5d, 0x6b, + 0x94, 0xf2, 0x9d, 0xe5, 0x4f, 0x37, 0x5a, 0xf2, 0x8e, 0xf8, 0x5d, 0x25, 0x15, 0x02, 0x23, 0x86, + 0xd5, 0xc8, 0x6e, 0xaf, 0xf9, 0x53, 0x41, 0x6b, 0xce, 0x6d, 0x87, 0x7c, 0x43, 0xfc, 0xf4, 0x8a, + 0xfc, 0x16, 0xb9, 0xe4, 0x45, 0xbf, 0xa7, 0x37, 0x70, 0x4e, 0xd7, 0xe8, 0x15, 0x6b, 0x4e, 0x59, + 0x7b, 0xbc, 0x29, 0x46, 0x27, 0x7f, 0xe5, 0x27, 0x35, 0x28, 0xb9, 0x5f, 0xfe, 0x99, 0x3e, 0xc8, + 0x91, 0x18, 0xa4, 0x24, 0xb7, 0x58, 0xf9, 0x05, 0x9b, 0xa1, 0xeb, 0x38, 0xd6, 0x1b, 0xf4, 0x95, + 0xa9, 0x63, 0xdd, 0xc0, 0x98, 0x01, 0x1f, 0xf1, 0x01, 0x40, 0x1a, 0xae, 0x26, 0x99, 0x70, 0xa9, + 0x16, 0xf0, 0x7c, 0x44, 0xdb, 0x96, 0x17, 0x15, 0x55, 0xe5, 0x2d, 0x7e, 0x4d, 0xa8, 0xab, 0x07, + 0x2a, 0xd0, 0x6a, 0x3a, 0x25, 0x76, 0x5c, 0xd9, 0x72, 0x4a, 0xb2, 0xed, 0x5b, 0xca, 0x4a, 0x47, + 0x6d, 0x1f, 0xc3, 0xfc, 0x5e, 0x18, 0x3e, 0x9d, 0x8c, 0xf5, 0x65, 0x93, 0x1d, 0xce, 0xdb, 0xf5, + 0xe2, 0x93, 0x4e, 0x66, 0x16, 0xf4, 0x3a, 0x36, 0xd5, 0x21, 0x6d, 0xa3, 0xa9, 0x8d, 0x0f, 0xd3, + 0x70, 0xf8, 0x47, 0xc4, 0x83, 0x45, 0xad, 0x03, 0xf5, 0xc0, 0x3b, 0x76, 0x33, 0x96, 0xe6, 0xcb, + 0x76, 0x61, 0x79, 0xb6, 0x6a, 0xb4, 0x1b, 0xb1, 0x6a, 0xf3, 0xb6, 0x43, 0x0e, 0xa0, 0xb1, 0xcd, + 0x7a, 0x61, 0x9f, 0xc9, 0x98, 0xd8, 0x52, 0x3a, 0x70, 0x1d, 0x4c, 0xeb, 0xcc, 0x5b, 0xa0, 0x6d, + 0x17, 0xc6, 0xde, 0x79, 0xc4, 0xbe, 0xb9, 0xf1, 0xa1, 0x8c, 0xb6, 0x7d, 0xa4, 0xec, 0x82, 0x0a, + 0x47, 0x5a, 0x76, 0x21, 0x13, 0xbf, 0xb4, 0xec, 0x42, 0x2e, 0x7e, 0x69, 0x2d, 0xb5, 0x0a, 0x87, + 0x92, 0x21, 0x2c, 0xe6, 0x42, 0x9e, 0xda, 0x24, 0x4c, 0x0b, 0x94, 0x76, 0xae, 0x4f, 0x27, 0xb0, + 0x7b, 0x5b, 0xb7, 0x7b, 0x3b, 0x84, 0xf9, 0x6d, 0x26, 0x16, 0x4b, 0xa4, 0xd1, 0x64, 0xf2, 0x9c, + 0xcd, 0x24, 0x9d, 0xac, 0x02, 0xc7, 0x3a, 0xdb, 0xf0, 0x63, 0x0e, 0x0b, 0xf9, 0x1a, 0xd4, 0xef, + 0xb3, 0x44, 0xe5, 0xcd, 0x68, 0xd7, 0x33, 0x93, 0x48, 0xd3, 0x29, 0x48, 0xbb, 0xb1, 0x79, 0x06, + 0x5b, 0xdb, 0x60, 0xfd, 0x01, 0x13, 0xca, 0xa9, 0xeb, 0xf7, 0x3f, 0x22, 0xff, 0x1f, 0x1b, 0xd7, + 0x89, 0x7b, 0xab, 0x46, 0xba, 0x85, 0xd9, 0xf8, 0x42, 0x06, 0x2f, 0x6a, 0x39, 0x08, 0xfb, 0xcc, + 0x70, 0x81, 0x02, 0xa8, 0x1b, 0xf9, 0xa6, 0x5a, 0x80, 0xf2, 0x99, 0xb6, 0x5a, 0x80, 0x0a, 0xd2, + 0x53, 0xe9, 0x1a, 0xf6, 0x43, 0xc9, 0xf5, 0xb4, 0x1f, 0x91, 0x92, 0x9a, 0xf6, 0xb4, 0xf1, 0xa1, + 0x37, 0x4a, 0x3e, 0x22, 0x4f, 0xf0, 0xb1, 0xb5, 0x99, 0x1b, 0x94, 0xfa, 0xd2, 0xd9, 0x34, 0x22, + 0xbd, 0x58, 0x46, 0x95, 0xed, 0x5f, 0x8b, 0xae, 0xd0, 0x53, 0xfa, 0x0c, 0xc0, 0x61, 0x12, 0x8e, + 0xb7, 0x3d, 0x36, 0x0a, 0x83, 0x54, 0xd7, 0xa6, 0xf9, 0x2f, 0xa9, 0xfe, 0x32, 0x92, 0x60, 0xc8, + 0x13, 0xe3, 0xf0, 0x61, 0xa5, 0x56, 0x29, 0xe6, 0x9a, 0x9a, 0x22, 0xa3, 0x17, 0xa4, 0x20, 0x4d, + 0xe6, 0xb6, 0x43, 0x36, 0x01, 0xd2, 0x98, 0xb7, 0x3e, 0x4a, 0xe4, 0xc2, 0xe9, 0x5a, 0xed, 0x15, + 0x04, 0xc8, 0x0f, 0xa0, 0x96, 0x06, 0x51, 0x2f, 0xa7, 0x19, 0xc6, 0x56, 0xc8, 0x55, 0x5b, 0xf0, + 0x5c, 0x68, 0x93, 0xb6, 0x70, 0xa9, 0x80, 0x54, 0xf9, 0x52, 0x61, 0xbc, 0xd2, 0x87, 0x25, 0x31, + 0x40, 0xed, 0x8e, 0x60, 0x46, 0x87, 0x9a, 0x49, 0x41, 0x78, 0x51, 0x4b, 0x73, 0x61, 0x74, 0xce, + 0x8a, 0x56, 0x70, 0x6e, 0x15, 0xd9, 0x24, 0x5c, 0x35, 0x8f, 0x60, 0x31, 0x17, 0x3e, 0xd2, 0x22, + 0x3d, 0x2d, 0xa2, 0xa7, 0x45, 0x7a, 0x6a, 0xe4, 0x89, 0xae, 0x60, 0x97, 0x0b, 0x14, 0xf0, 0x04, + 0x74, 0xe6, 0x27, 0xbd, 0x93, 0x77, 0x9c, 0xf5, 0xbb, 0x37, 0xdf, 0xff, 0x5f, 0x03, 0x3f, 0x39, + 0x99, 0x1c, 0xdd, 0xea, 0x85, 0xa3, 0x8d, 0xa1, 0x0a, 0x29, 0xc8, 0xbc, 0xac, 0x8d, 0x61, 0xd0, + 0xdf, 0xc0, 0x96, 0x8f, 0x66, 0xf1, 0xc7, 0x69, 0x3f, 0xf5, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, + 0x9a, 0x9c, 0xe5, 0xb2, 0xce, 0x56, 0x00, 0x00, } diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 4a87628422..77a615d583 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -1479,6 +1479,11 @@ message QueryRoutesRequest { send the payment. */ FeeLimit fee_limit = 5; + + /** + An optional list of nodes and channels the route must pass through in that order. + */ + RoutePeg route_peg = 6; } message QueryRoutesResponse { repeated Route routes = 1 [json_name = "routes"]; @@ -1719,6 +1724,21 @@ message ClosedChannelUpdate { ChannelPoint chan_point = 4; } +message HopPeg { + /// The public key of the pegged node. + string node_id = 1 [json_name = "node_id"]; + + /// Optional. If not 0, the unique identifier of the pegged channel leading to the node. + uint64 chan_id = 2 [json_name = "chan_id"]; +} + +message RoutePeg { + /** + A list of hop pegs that that the selected route needs to pass through in that order. + */ + repeated HopPeg hop_pegs = 1 [json_name = "hop_pegs"]; +} + message HopHint { /// The public key of the node at the start of the channel. string node_id = 1 [json_name = "node_id"]; diff --git a/rpcserver.go b/rpcserver.go index 519098404d..35ec2eb1b5 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3992,6 +3992,29 @@ func (r *rpcServer) QueryRoutes(ctx context.Context, feeLimit := calculateFeeLimit(in.FeeLimit, amtMSat) + var pegs []routing.HopPeg + for _, p := range in.GetRoutePeg().GetHopPegs() { + if len(p.NodeId) == 0 { + return nil, fmt.Errorf("Peg node Id is " + + "missing") + } + nodeIDBytes, err := hex.DecodeString(p.NodeId) + if err != nil { + return nil, fmt.Errorf("Failed to decode " + + "peg node Id") + } + nodeID, err := btcec.ParsePubKey(nodeIDBytes, + btcec.S256()) + if err != nil { + return nil, fmt.Errorf("Failed to parse " + + "peg public key from node Id") + } + pegs = append(pegs, routing.HopPeg{ + NodeID: nodeID, + ChannelID: p.ChanId, + }) + } + // numRoutes will default to 10 if not specified explicitly. numRoutesIn := uint32(in.NumRoutes) if numRoutesIn == 0 { @@ -4007,11 +4030,11 @@ func (r *rpcServer) QueryRoutes(ctx context.Context, ) if in.FinalCltvDelta == 0 { routes, findErr = r.server.chanRouter.FindRoutes( - pubKey, amtMSat, feeLimit, nil, numRoutesIn, + pubKey, amtMSat, feeLimit, pegs, numRoutesIn, ) } else { routes, findErr = r.server.chanRouter.FindRoutes( - pubKey, amtMSat, feeLimit, nil, numRoutesIn, + pubKey, amtMSat, feeLimit, pegs, numRoutesIn, uint16(in.FinalCltvDelta), ) } From 20a519f9a5fe1d7436f296dd585db237090f94a2 Mon Sep 17 00:00:00 2001 From: bluetegu Date: Fri, 8 Feb 2019 06:33:22 -0500 Subject: [PATCH 3/3] lncli: add optional pegs parameter to queryroutes. The list of pegged hops force route to pass through specified nodes and channels. --- cmd/lncli/commands.go | 59 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 2a4874eaa1..258cc77992 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -2824,11 +2824,37 @@ func getNodeInfo(ctx *cli.Context) error { } var queryRoutesCommand = cli.Command{ - Name: "queryroutes", - Category: "Payments", - Usage: "Query a route to a destination.", - Description: "Queries the channel router for a potential path to the destination that has sufficient flow for the amount including fees", - ArgsUsage: "dest amt", + Name: "queryroutes", + Category: "Payments", + Usage: "Query a route to a destination.", + Description: ` + Queries the channel router for a potential path to the destination that + has sufficient flow for the amount including fees. + + A series of nodes and channels the route must pass through can optionally + be provided. The node id is mandatory. The channel leading to this node + can optionally be pegged too, otherwise the channel id should be set to 0. + The resulting route is composed of segments connecting between the pegged + nodes. Each segment does not have loops, but the entire path may. The + route selection assures that no edge will be transversed twice at the + same direction. + The alternate routes are stitched from N-1 shortest segment paths and + one alternate segment path. + + Below is an example of a query using routing pegs: + + lncli queryroutes --pegs='{"hop_pegs": [ + { + "node_id": "026a52eadd42eabb70e9b0481af7001d299f7d7b41030977bb37a2faac7bbe0012", + "chan_id": "2043992116101120" + } + ] + }' "034a15c028970d4070c60f532018cfdb943b584ba267c83fe333ef1ad70b10feaf" 333 + + Note the single quote used to encapsulate the pegs. + `, + + ArgsUsage: "dest amt", Flags: []cli.Flag{ cli.StringFlag{ Name: "dest", @@ -2859,6 +2885,14 @@ var queryRoutesCommand = cli.Command{ Usage: "(optional) number of blocks the last hop has to reveal " + "the preimage", }, + cli.StringFlag{ + Name: "pegs", + Usage: "(optional) a json array string of nodes and channels the " + + "route must path through. Each pegged hop must contain the " + + "public key of the node that the route must path through, " + + "and optionally a channel id leading to that node that the " + + "route should path through, or otherwise set as 0.", + }, }, Action: actionDecorator(queryRoutes), } @@ -2903,12 +2937,27 @@ func queryRoutes(ctx *cli.Context) error { return err } + var routePeg *lnrpc.RoutePeg + if ctx.IsSet("pegs") { + jsonPegs := ctx.String("pegs") + pegs := &lnrpc.RoutePeg{} + err = jsonpb.UnmarshalString(jsonPegs, pegs) + if err != nil { + return fmt.Errorf("unable to unmarshal json string "+ + "from incoming array of pegs: %v", err) + } + routePeg = &lnrpc.RoutePeg{ + HopPegs: pegs.HopPegs, + } + } + req := &lnrpc.QueryRoutesRequest{ PubKey: dest, Amt: amt, FeeLimit: feeLimit, NumRoutes: int32(ctx.Int("num_max_routes")), FinalCltvDelta: int32(ctx.Int("final_cltv_delta")), + RoutePeg: routePeg, } route, err := client.QueryRoutes(ctxb, req)