Browse Source

Merge pull request #5159 from halseth/amp-sendpayment

AMP support for SendPaymentV2
master
Conner Fromknecht 3 years ago committed by GitHub
parent
commit
d771ed7616
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      amp/derivation_test.go
  2. 165
      amp/shard_tracker.go
  3. 95
      amp/shard_tracker_test.go
  4. 36
      amp/sharer.go
  5. 2
      channeldb/duplicate_payments.go
  6. 7
      channeldb/mp_payment.go
  7. 30
      channeldb/payment_control.go
  8. 194
      channeldb/payment_control_test.go
  9. 43
      channeldb/payments.go
  10. 41
      channeldb/payments_test.go
  11. 51
      htlcswitch/switch.go
  12. 390
      lnrpc/routerrpc/router.pb.go
  13. 5
      lnrpc/routerrpc/router.proto
  14. 9
      lnrpc/routerrpc/router.swagger.json
  15. 103
      lnrpc/routerrpc/router_backend.go
  16. 16
      lnrpc/routerrpc/router_server.go
  17. 1601
      lnrpc/rpc.pb.go
  18. 2
      lnrpc/rpc.proto
  19. 8
      lnrpc/rpc.swagger.json
  20. 124
      lntest/itest/lnd_amp_test.go
  21. 4
      lntest/itest/lnd_multi-hop-error-propagation_test.go
  22. 5
      lntest/itest/lnd_send_multi_path_payment_test.go
  23. 9
      lntest/itest/lnd_single_hop_invoice_test.go
  24. 24
      lntest/itest/lnd_test.go
  25. 5
      lntest/itest/lnd_test_list_on_test.go
  26. 20
      lntest/itest/log_error_whitelist.txt
  27. 4
      routing/control_tower.go
  28. 32
      routing/control_tower_test.go
  29. 5
      routing/integrated_routing_context_test.go
  30. 20
      routing/mock_test.go
  31. 2
      routing/pathfind.go
  32. 158
      routing/payment_lifecycle.go
  33. 2
      routing/payment_lifecycle_test.go
  34. 2
      routing/payment_session.go
  35. 5
      routing/payment_session_test.go
  36. 243
      routing/router.go
  37. 26
      routing/router_test.go
  38. 135
      routing/shards/shard_tracker.go
  39. 47
      routing/shards/shard_tracker_test.go
  40. 5
      rpcserver.go

28
amp/derivation_test.go

@ -10,6 +10,7 @@ import (
type sharerTest struct {
name string
numShares int
merge bool
}
var sharerTests = []sharerTest{
@ -25,6 +26,16 @@ var sharerTests = []sharerTest{
name: "many shares",
numShares: 10,
},
{
name: "merge 4 shares",
numShares: 4,
merge: true,
},
{
name: "merge many shares",
numShares: 20,
merge: true,
},
}
// TestSharer executes the end-to-end derivation between sender and receiver,
@ -71,10 +82,27 @@ func testSharer(t *testing.T, test sharerTest) {
// Compute the final share and finalize the sharing.
child := sharer.Child(0)
sharer = sharer.Zero()
assertChildShare(t, child, 0)
children = append(children, child)
// If we are testing merging, merge half of the created children back
// into the sharer.
if test.merge {
for i := len(children) / 2; i < len(children); i++ {
sharer = sharer.Merge(children[i])
}
children = children[:len(children)/2]
// We must create a new last child from what we just merged
// back.
child := sharer.Child(0)
assertChildShare(t, child, 0)
children = append(children, child)
}
assertReconstruction(t, children...)
}

165
amp/shard_tracker.go

@ -0,0 +1,165 @@
package amp
import (
"crypto/rand"
"encoding/binary"
"fmt"
"sync"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/shards"
)
// Shard is an implementation of the shards.PaymentShards interface specific
// to AMP payments.
type Shard struct {
child *Child
mpp *record.MPP
amp *record.AMP
}
// A compile time check to ensure Shard implements the shards.PaymentShard
// interface.
var _ shards.PaymentShard = (*Shard)(nil)
// Hash returns the hash used for the HTLC representing this AMP shard.
func (s *Shard) Hash() lntypes.Hash {
return s.child.Hash
}
// MPP returns any extra MPP records that should be set for the final hop on
// the route used by this shard.
func (s *Shard) MPP() *record.MPP {
return s.mpp
}
// AMP returns any extra AMP records that should be set for the final hop on
// the route used by this shard.
func (s *Shard) AMP() *record.AMP {
return s.amp
}
// ShardTracker is an implementation of the shards.ShardTracker interface
// that is able to generate payment shards according to the AMP splitting
// algorithm. It can be used to generate new hashes to use for HTLCs, and also
// cancel shares used for failed payment shards.
type ShardTracker struct {
setID [32]byte
paymentAddr [32]byte
totalAmt lnwire.MilliSatoshi
sharer Sharer
shards map[uint64]*Child
sync.Mutex
}
// A compile time check to ensure ShardTracker implements the
// shards.ShardTracker interface.
var _ shards.ShardTracker = (*ShardTracker)(nil)
// NewShardTracker creates a new shard tracker to use for AMP payments. The
// root shard, setID, payment address and total amount must be correctly set in
// order for the TLV options to include with each shard to be created
// correctly.
func NewShardTracker(root, setID, payAddr [32]byte,
totalAmt lnwire.MilliSatoshi) *ShardTracker {
// Create a new seed sharer from this root.
rootShare := Share(root)
rootSharer := SeedSharerFromRoot(&rootShare)
return &ShardTracker{
setID: setID,
paymentAddr: payAddr,
totalAmt: totalAmt,
sharer: rootSharer,
shards: make(map[uint64]*Child),
}
}
// NewShard registers a new attempt with the ShardTracker and returns a
// new shard representing this attempt. This attempt's shard should be canceled
// if it ends up not being used by the overall payment, i.e. if the attempt
// fails.
func (s *ShardTracker) NewShard(pid uint64, last bool) (shards.PaymentShard,
error) {
s.Lock()
defer s.Unlock()
// Use a random child index.
var childIndex [4]byte
if _, err := rand.Read(childIndex[:]); err != nil {
return nil, err
}
idx := binary.BigEndian.Uint32(childIndex[:])
// Depending on whether we are requesting the last shard or not, either
// split the current share into two, or get a Child directly from the
// current sharer.
var child *Child
if last {
child = s.sharer.Child(idx)
// If this was the last shard, set the current share to the
// zero share to indicate we cannot split it further.
s.sharer = s.sharer.Zero()
} else {
left, sharer, err := s.sharer.Split()
if err != nil {
return nil, err
}
s.sharer = sharer
child = left.Child(idx)
}
// Track the new child and return the shard.
s.shards[pid] = child
mpp := record.NewMPP(s.totalAmt, s.paymentAddr)
amp := record.NewAMP(
child.ChildDesc.Share, s.setID, child.ChildDesc.Index,
)
return &Shard{
child: child,
mpp: mpp,
amp: amp,
}, nil
}
// CancelShard cancel's the shard corresponding to the given attempt ID.
func (s *ShardTracker) CancelShard(pid uint64) error {
s.Lock()
defer s.Unlock()
c, ok := s.shards[pid]
if !ok {
return fmt.Errorf("pid not found")
}
delete(s.shards, pid)
// Now that we are canceling this shard, we XOR the share back into our
// current share.
s.sharer = s.sharer.Merge(c)
return nil
}
// GetHash retrieves the hash used by the shard of the given attempt ID. This
// will return an error if the attempt ID is unknown.
func (s *ShardTracker) GetHash(pid uint64) (lntypes.Hash, error) {
s.Lock()
defer s.Unlock()
c, ok := s.shards[pid]
if !ok {
return lntypes.Hash{}, fmt.Errorf("AMP shard for attempt %v "+
"not found", pid)
}
return c.Hash, nil
}

95
amp/shard_tracker_test.go

@ -0,0 +1,95 @@
package amp_test
import (
"crypto/rand"
"testing"
"github.com/lightningnetwork/lnd/amp"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/shards"
"github.com/stretchr/testify/require"
)
// TestAMPShardTracker tests that we can derive and cancel shards at will using
// the AMP shard tracker.
func TestAMPShardTracker(t *testing.T) {
var root, setID, payAddr [32]byte
_, err := rand.Read(root[:])
require.NoError(t, err)
_, err = rand.Read(setID[:])
require.NoError(t, err)
_, err = rand.Read(payAddr[:])
require.NoError(t, err)
var totalAmt lnwire.MilliSatoshi = 1000
// Create an AMP shard tracker using the random data we just generated.
tracker := amp.NewShardTracker(root, setID, payAddr, totalAmt)
// Trying to retrieve a hash for id 0 should result in an error.
_, err = tracker.GetHash(0)
require.Error(t, err)
// We start by creating 20 shards.
const numShards = 20
var shards []shards.PaymentShard
for i := uint64(0); i < numShards; i++ {
s, err := tracker.NewShard(i, i == numShards-1)
require.NoError(t, err)
// Check that the shards have their payloads set as expected.
require.Equal(t, setID, s.AMP().SetID())
require.Equal(t, totalAmt, s.MPP().TotalMsat())
require.Equal(t, payAddr, s.MPP().PaymentAddr())
shards = append(shards, s)
}
// Make sure we can retrieve the hash for all of them.
for i := uint64(0); i < numShards; i++ {
hash, err := tracker.GetHash(i)
require.NoError(t, err)
require.Equal(t, shards[i].Hash(), hash)
}
// Now cancel half of the shards.
j := 0
for i := uint64(0); i < numShards; i++ {
if i%2 == 0 {
err := tracker.CancelShard(i)
require.NoError(t, err)
continue
}
// Keep shard.
shards[j] = shards[i]
j++
}
shards = shards[:j]
// Get a new last shard.
s, err := tracker.NewShard(numShards, true)
require.NoError(t, err)
shards = append(shards, s)
// Finally make sure these shards together can be used to reconstruct
// the children.
childDescs := make([]amp.ChildDesc, len(shards))
for i, s := range shards {
childDescs[i] = amp.ChildDesc{
Share: s.AMP().RootShare(),
Index: s.AMP().ChildIndex(),
}
}
// Using the child descriptors, reconstruct the children.
children := amp.ReconstructChildren(childDescs...)
// Validate that the derived child preimages match the hash of each shard.
for i, child := range children {
require.Equal(t, shards[i].Hash(), child.Hash)
}
}

36
amp/sharer.go

@ -2,8 +2,12 @@ package amp
import (
"crypto/rand"
"fmt"
)
// zeroShare is the all-zero 32-byte share.
var zeroShare = Share{}
// Sharer facilitates dynamic splitting of a root share value and derivation of
// child preimage and hashes for individual HTLCs in an AMP payment. A sharer
// represents a specific node in an abstract binary tree that can generate up to
@ -34,6 +38,16 @@ type Sharer interface {
// that the shares of all nodes descending from the parent will XOR to
// the parent's share.
Split() (Sharer, Sharer, error)
// Merge takes the given Child and "merges" it into the Sharer by
// XOR-ing its share with the Sharer's current share.
Merge(*Child) Sharer
// Zero returns a a new "zero Sharer" that has its current share set to
// zero, while keeping the root share. Merging a Child from the
// original Sharer into this zero-Sharer gives back the original
// Sharer.
Zero() Sharer
}
// SeedSharer orchestrates the sharing of the root AMP seed along multiple
@ -81,6 +95,11 @@ func (s *SeedSharer) Root() Share {
// parent share should no longer be used, and the caller should use the Child
// method on each to derive preimage/hash pairs for the HTLCs.
func (s *SeedSharer) Split() (Sharer, Sharer, error) {
// We cannot split the zero-Sharer.
if s.curr == zeroShare {
return nil, nil, fmt.Errorf("cannot split zero-Sharer")
}
shareLeft, shareRight, err := split(&s.curr)
if err != nil {
return nil, nil, err
@ -92,6 +111,23 @@ func (s *SeedSharer) Split() (Sharer, Sharer, error) {
return left, right, nil
}
// Merge takes the given Child and "merges" it into the Sharer by XOR-ing its
// share with the Sharer's current share.
func (s *SeedSharer) Merge(child *Child) Sharer {
var curr Share
curr.Xor(&s.curr, &child.Share)
sharer := initSeedSharer(&s.root, &curr)
return sharer
}
// Zero returns a a new "zero Sharer" that has its current share set to zero,
// while keeping the root share. Merging a Child from the original Sharer into
// this zero-Sharer gives back the original Sharer.
func (s *SeedSharer) Zero() Sharer {
return initSeedSharer(&s.root, &zeroShare)
}
// Child derives a preimage/hash pair to be used for an AMP HTLC.
// All children of s will use the same underlying share, but have unique
// preimage and hash. This can be used to rerandomize the preimage/hash pair for

2
channeldb/duplicate_payments.go

@ -99,7 +99,7 @@ func deserializeDuplicatePaymentCreationInfo(r io.Reader) (
c := &PaymentCreationInfo{}
if _, err := io.ReadFull(r, c.PaymentHash[:]); err != nil {
if _, err := io.ReadFull(r, c.PaymentIdentifier[:]); err != nil {
return nil, err
}

7
channeldb/mp_payment.go

@ -29,6 +29,13 @@ type HTLCAttemptInfo struct {
// AttemptTime is the time at which this HTLC was attempted.
AttemptTime time.Time
// Hash is the hash used for this single HTLC attempt. For AMP payments
// this will differ across attempts, for non-AMP payments each attempt
// will use the same hash. This can be nil for older payment attempts,
// in which the payment's PaymentHash in the PaymentCreationInfo should
// be used.
Hash *lntypes.Hash
}
// HTLCAttempt contains information about a specific HTLC attempt for a given

30
channeldb/payment_control.go

@ -173,8 +173,10 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash,
// Once we have obtained a sequence number, we add an entry
// to our index bucket which will map the sequence number to
// our payment hash.
err = createPaymentIndexEntry(tx, sequenceNum, info.PaymentHash)
// our payment identifier.
err = createPaymentIndexEntry(
tx, sequenceNum, info.PaymentIdentifier,
)
if err != nil {
return err
}
@ -220,12 +222,12 @@ const paymentIndexTypeHash paymentIndexType = 0
// createPaymentIndexEntry creates a payment hash typed index for a payment. The
// index produced contains a payment index type (which can be used in future to
// signal different payment index types) and the payment hash.
// signal different payment index types) and the payment identifier.
func createPaymentIndexEntry(tx kvdb.RwTx, sequenceNumber []byte,
hash lntypes.Hash) error {
id lntypes.Hash) error {
var b bytes.Buffer
if err := WriteElements(&b, paymentIndexTypeHash, hash[:]); err != nil {
if err := WriteElements(&b, paymentIndexTypeHash, id[:]); err != nil {
return err
}
@ -676,16 +678,9 @@ func ensureInFlight(payment *MPPayment) error {
}
}
// InFlightPayment is a wrapper around the info for a payment that has status
// InFlight.
type InFlightPayment struct {
// Info is the PaymentCreationInfo of the in-flight payment.
Info *PaymentCreationInfo
}
// FetchInFlightPayments returns all payments with status InFlight.
func (p *PaymentControl) FetchInFlightPayments() ([]*InFlightPayment, error) {
var inFlights []*InFlightPayment
func (p *PaymentControl) FetchInFlightPayments() ([]*MPPayment, error) {
var inFlights []*MPPayment
err := kvdb.View(p.db, func(tx kvdb.RTx) error {
payments := tx.ReadBucket(paymentsRootBucket)
if payments == nil {
@ -708,15 +703,12 @@ func (p *PaymentControl) FetchInFlightPayments() ([]*InFlightPayment, error) {
return nil
}
inFlight := &InFlightPayment{}
// Get the CreationInfo.
inFlight.Info, err = fetchCreationInfo(bucket)
p, err := fetchPayment(bucket)
if err != nil {
return err
}
inFlights = append(inFlights, inFlight)
inFlights = append(inFlights, p)
return nil
})
}, func() {

194
channeldb/payment_control_test.go

@ -38,10 +38,10 @@ func genInfo() (*PaymentCreationInfo, *HTLCAttemptInfo,
rhash := sha256.Sum256(preimage[:])
return &PaymentCreationInfo{
PaymentHash: rhash,
Value: testRoute.ReceiverAmt(),
CreationTime: time.Unix(time.Now().Unix(), 0),
PaymentRequest: []byte("hola"),
PaymentIdentifier: rhash,
Value: testRoute.ReceiverAmt(),
CreationTime: time.Unix(time.Now().Unix(), 0),
PaymentRequest: []byte("hola"),
},
&HTLCAttemptInfo{
AttemptID: 0,
@ -70,63 +70,63 @@ func TestPaymentControlSwitchFail(t *testing.T) {
}
// Sends base htlc message which initiate StatusInFlight.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
assertPaymentIndex(t, pControl, info.PaymentHash)
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentIndex(t, pControl, info.PaymentIdentifier)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, nil,
t, pControl, info.PaymentIdentifier, info, nil, nil,
)
// Fail the payment, which should moved it to Failed.
failReason := FailureReasonNoRoute
_, err = pControl.Fail(info.PaymentHash, failReason)
_, err = pControl.Fail(info.PaymentIdentifier, failReason)
if err != nil {
t.Fatalf("unable to fail payment hash: %v", err)
}
// Verify the status is indeed Failed.
assertPaymentStatus(t, pControl, info.PaymentHash, StatusFailed)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusFailed)
assertPaymentInfo(
t, pControl, info.PaymentHash, info, &failReason, nil,
t, pControl, info.PaymentIdentifier, info, &failReason, nil,
)
// Lookup the payment so we can get its old sequence number before it is
// overwritten.
payment, err := pControl.FetchPayment(info.PaymentHash)
payment, err := pControl.FetchPayment(info.PaymentIdentifier)
assert.NoError(t, err)
// Sends the htlc again, which should succeed since the prior payment
// failed.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
// Check that our index has been updated, and the old index has been
// removed.
assertPaymentIndex(t, pControl, info.PaymentHash)
assertPaymentIndex(t, pControl, info.PaymentIdentifier)
assertNoIndex(t, pControl, payment.SequenceNum)
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, nil,
t, pControl, info.PaymentIdentifier, info, nil, nil,
)
// Record a new attempt. In this test scenario, the attempt fails.
// However, this is not communicated to control tower in the current
// implementation. It only registers the initiation of the attempt.
_, err = pControl.RegisterAttempt(info.PaymentHash, attempt)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatalf("unable to register attempt: %v", err)
}
htlcReason := HTLCFailUnreadable
_, err = pControl.FailAttempt(
info.PaymentHash, attempt.AttemptID,
info.PaymentIdentifier, attempt.AttemptID,
&HTLCFailInfo{
Reason: htlcReason,
},
@ -134,35 +134,35 @@ func TestPaymentControlSwitchFail(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
htlc := &htlcStatus{
HTLCAttemptInfo: attempt,
failure: &htlcReason,
}
assertPaymentInfo(t, pControl, info.PaymentHash, info, nil, htlc)
assertPaymentInfo(t, pControl, info.PaymentIdentifier, info, nil, htlc)
// Record another attempt.
attempt.AttemptID = 1
_, err = pControl.RegisterAttempt(info.PaymentHash, attempt)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
htlc = &htlcStatus{
HTLCAttemptInfo: attempt,
}
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
// Settle the attempt and verify that status was changed to
// StatusSucceeded.
payment, err = pControl.SettleAttempt(
info.PaymentHash, attempt.AttemptID,
info.PaymentIdentifier, attempt.AttemptID,
&HTLCSettleInfo{
Preimage: preimg,
},
@ -183,16 +183,16 @@ func TestPaymentControlSwitchFail(t *testing.T) {
spew.Sdump(payment.HTLCs[0].Route), err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusSucceeded)
htlc.settle = &preimg
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
// Attempt a final payment, which should now fail since the prior
// payment succeed.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != ErrAlreadyPaid {
t.Fatalf("unable to send htlc message: %v", err)
}
@ -219,42 +219,42 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) {
// Sends base htlc message which initiate base status and move it to
// StatusInFlight and verifies that it was changed.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
assertPaymentIndex(t, pControl, info.PaymentHash)
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentIndex(t, pControl, info.PaymentIdentifier)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, nil,
t, pControl, info.PaymentIdentifier, info, nil, nil,
)
// Try to initiate double sending of htlc message with the same
// payment hash, should result in error indicating that payment has
// already been sent.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != ErrPaymentInFlight {
t.Fatalf("payment control wrong behaviour: " +
"double sending must trigger ErrPaymentInFlight error")
}
// Record an attempt.
_, err = pControl.RegisterAttempt(info.PaymentHash, attempt)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
htlc := &htlcStatus{
HTLCAttemptInfo: attempt,
}
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
// Sends base htlc message which initiate StatusInFlight.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != ErrPaymentInFlight {
t.Fatalf("payment control wrong behaviour: " +
"double sending must trigger ErrPaymentInFlight error")
@ -262,7 +262,7 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) {
// After settling, the error should be ErrAlreadyPaid.
_, err = pControl.SettleAttempt(
info.PaymentHash, attempt.AttemptID,
info.PaymentIdentifier, attempt.AttemptID,
&HTLCSettleInfo{
Preimage: preimg,
},
@ -270,12 +270,12 @@ func TestPaymentControlSwitchDoubleSend(t *testing.T) {
if err != nil {
t.Fatalf("error shouldn't have been received, got: %v", err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusSucceeded)
htlc.settle = &preimg
assertPaymentInfo(t, pControl, info.PaymentHash, info, nil, htlc)
assertPaymentInfo(t, pControl, info.PaymentIdentifier, info, nil, htlc)
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != ErrAlreadyPaid {
t.Fatalf("unable to send htlc message: %v", err)
}
@ -302,7 +302,7 @@ func TestPaymentControlSuccessesWithoutInFlight(t *testing.T) {
// Attempt to complete the payment should fail.
_, err = pControl.SettleAttempt(
info.PaymentHash, 0,
info.PaymentIdentifier, 0,
&HTLCSettleInfo{
Preimage: preimg,
},
@ -311,7 +311,7 @@ func TestPaymentControlSuccessesWithoutInFlight(t *testing.T) {
t.Fatalf("expected ErrPaymentNotInitiated, got %v", err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusUnknown)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusUnknown)
}
// TestPaymentControlFailsWithoutInFlight checks that a strict payment
@ -334,12 +334,12 @@ func TestPaymentControlFailsWithoutInFlight(t *testing.T) {
}
// Calling Fail should return an error.
_, err = pControl.Fail(info.PaymentHash, FailureReasonNoRoute)
_, err = pControl.Fail(info.PaymentIdentifier, FailureReasonNoRoute)
if err != ErrPaymentNotInitiated {
t.Fatalf("expected ErrPaymentNotInitiated, got %v", err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusUnknown)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusUnknown)
}
// TestPaymentControlDeleteNonInFlight checks that calling DeletePayments only
@ -397,11 +397,11 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) {
}
// Sends base htlc message which initiate StatusInFlight.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
_, err = pControl.RegisterAttempt(info.PaymentHash, attempt)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
@ -414,7 +414,7 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) {
// Fail the payment attempt.
htlcFailure := HTLCFailUnreadable
_, err := pControl.FailAttempt(
info.PaymentHash, attempt.AttemptID,
info.PaymentIdentifier, attempt.AttemptID,
&HTLCFailInfo{
Reason: htlcFailure,
},
@ -425,23 +425,23 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) {
// Fail the payment, which should moved it to Failed.
failReason := FailureReasonNoRoute
_, err = pControl.Fail(info.PaymentHash, failReason)
_, err = pControl.Fail(info.PaymentIdentifier, failReason)
if err != nil {
t.Fatalf("unable to fail payment hash: %v", err)
}
// Verify the status is indeed Failed.
assertPaymentStatus(t, pControl, info.PaymentHash, StatusFailed)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusFailed)
htlc.failure = &htlcFailure
assertPaymentInfo(
t, pControl, info.PaymentHash, info,
t, pControl, info.PaymentIdentifier, info,
&failReason, htlc,
)
} else if p.success {
// Verifies that status was changed to StatusSucceeded.
_, err := pControl.SettleAttempt(
info.PaymentHash, attempt.AttemptID,
info.PaymentIdentifier, attempt.AttemptID,
&HTLCSettleInfo{
Preimage: preimg,
},
@ -450,18 +450,18 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) {
t.Fatalf("error shouldn't have been received, got: %v", err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusSucceeded)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusSucceeded)
htlc.settle = &preimg
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
numSuccess++
} else {
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
numInflight++
@ -471,7 +471,7 @@ func TestPaymentControlDeleteNonInFligt(t *testing.T) {
// add one.
if p.hasDuplicate {
appendDuplicatePayment(
t, pControl.db, info.PaymentHash,
t, pControl.db, info.PaymentIdentifier,
uint64(duplicateSeqNr), preimg,
)
duplicateSeqNr++
@ -582,20 +582,20 @@ func TestPaymentControlDeletePayments(t *testing.T) {
attemptID++
// Init the payment.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
// Register and fail the first attempt for all three payments.
_, err = pControl.RegisterAttempt(info.PaymentHash, attempt)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
htlcFailure := HTLCFailUnreadable
_, err = pControl.FailAttempt(
info.PaymentHash, attempt.AttemptID,
info.PaymentIdentifier, attempt.AttemptID,
&HTLCFailInfo{
Reason: htlcFailure,
},
@ -609,7 +609,7 @@ func TestPaymentControlDeletePayments(t *testing.T) {
attempt.AttemptID = attemptID
attemptID++
_, err = pControl.RegisterAttempt(info.PaymentHash, attempt)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
@ -620,7 +620,7 @@ func TestPaymentControlDeletePayments(t *testing.T) {
case 0:
htlcFailure := HTLCFailUnreadable
_, err = pControl.FailAttempt(
info.PaymentHash, attempt.AttemptID,
info.PaymentIdentifier, attempt.AttemptID,
&HTLCFailInfo{
Reason: htlcFailure,
},
@ -630,7 +630,7 @@ func TestPaymentControlDeletePayments(t *testing.T) {
}
failReason := FailureReasonNoRoute
_, err = pControl.Fail(info.PaymentHash, failReason)
_, err = pControl.Fail(info.PaymentIdentifier, failReason)
if err != nil {
t.Fatalf("unable to fail payment hash: %v", err)
}
@ -638,7 +638,7 @@ func TestPaymentControlDeletePayments(t *testing.T) {
// Settle the attempt
case 1:
_, err := pControl.SettleAttempt(
info.PaymentHash, attempt.AttemptID,
info.PaymentIdentifier, attempt.AttemptID,
&HTLCSettleInfo{
Preimage: preimg,
},
@ -807,15 +807,15 @@ func TestPaymentControlMultiShard(t *testing.T) {
}
// Init the payment, moving it to the StatusInFlight state.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
assertPaymentIndex(t, pControl, info.PaymentHash)
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentIndex(t, pControl, info.PaymentIdentifier)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, nil,
t, pControl, info.PaymentIdentifier, info, nil, nil,
)
// Create three unique attempts we'll use for the test, and
@ -834,19 +834,19 @@ func TestPaymentControlMultiShard(t *testing.T) {
a.AttemptID = i
attempts = append(attempts, &a)
_, err = pControl.RegisterAttempt(info.PaymentHash, &a)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, &a)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
assertPaymentStatus(
t, pControl, info.PaymentHash, StatusInFlight,
t, pControl, info.PaymentIdentifier, StatusInFlight,
)
htlc := &htlcStatus{
HTLCAttemptInfo: &a,
}
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
}
@ -855,7 +855,7 @@ func TestPaymentControlMultiShard(t *testing.T) {
// will be too large.
b := *attempt
b.AttemptID = 3
_, err = pControl.RegisterAttempt(info.PaymentHash, &b)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrValueExceedsAmt {
t.Fatalf("expected ErrValueExceedsAmt, got: %v",
err)
@ -865,7 +865,7 @@ func TestPaymentControlMultiShard(t *testing.T) {
a := attempts[1]
htlcFail := HTLCFailUnreadable
_, err = pControl.FailAttempt(
info.PaymentHash, a.AttemptID,
info.PaymentIdentifier, a.AttemptID,
&HTLCFailInfo{
Reason: htlcFail,
},
@ -879,11 +879,11 @@ func TestPaymentControlMultiShard(t *testing.T) {
failure: &htlcFail,
}
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
// Payment should still be in-flight.
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
// Depending on the test case, settle or fail the first attempt.
a = attempts[0]
@ -894,7 +894,7 @@ func TestPaymentControlMultiShard(t *testing.T) {
var firstFailReason *FailureReason
if test.settleFirst {
_, err := pControl.SettleAttempt(
info.PaymentHash, a.AttemptID,
info.PaymentIdentifier, a.AttemptID,
&HTLCSettleInfo{
Preimage: preimg,
},
@ -907,11 +907,11 @@ func TestPaymentControlMultiShard(t *testing.T) {
// Assert that the HTLC has had the preimage recorded.
htlc.settle = &preimg
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
} else {
_, err := pControl.FailAttempt(
info.PaymentHash, a.AttemptID,
info.PaymentIdentifier, a.AttemptID,
&HTLCFailInfo{
Reason: htlcFail,
},
@ -924,13 +924,13 @@ func TestPaymentControlMultiShard(t *testing.T) {
// Assert the failure was recorded.
htlc.failure = &htlcFail
assertPaymentInfo(
t, pControl, info.PaymentHash, info, nil, htlc,
t, pControl, info.PaymentIdentifier, info, nil, htlc,
)
// We also record a payment level fail, to move it into
// a terminal state.
failReason := FailureReasonNoRoute
_, err = pControl.Fail(info.PaymentHash, failReason)
_, err = pControl.Fail(info.PaymentIdentifier, failReason)
if err != nil {
t.Fatalf("unable to fail payment hash: %v", err)
}
@ -942,18 +942,18 @@ func TestPaymentControlMultiShard(t *testing.T) {
// The payment should still be considered in-flight, since there
// is still an active HTLC.
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
// Try to register yet another attempt. This should fail now
// that the payment has reached a terminal condition.
b = *attempt
b.AttemptID = 3
_, err = pControl.RegisterAttempt(info.PaymentHash, &b)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrPaymentTerminal {
t.Fatalf("expected ErrPaymentTerminal, got: %v", err)
}
assertPaymentStatus(t, pControl, info.PaymentHash, StatusInFlight)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, StatusInFlight)
// Settle or fail the remaining attempt based on the testcase.
a = attempts[2]
@ -963,7 +963,7 @@ func TestPaymentControlMultiShard(t *testing.T) {
if test.settleLast {
// Settle the last outstanding attempt.
_, err = pControl.SettleAttempt(
info.PaymentHash, a.AttemptID,
info.PaymentIdentifier, a.AttemptID,
&HTLCSettleInfo{
Preimage: preimg,
},
@ -975,13 +975,13 @@ func TestPaymentControlMultiShard(t *testing.T) {
htlc.settle = &preimg
assertPaymentInfo(
t, pControl, info.PaymentHash, info,
t, pControl, info.PaymentIdentifier, info,
firstFailReason, htlc,
)
} else {
// Fail the attempt.
_, err := pControl.FailAttempt(
info.PaymentHash, a.AttemptID,
info.PaymentIdentifier, a.AttemptID,
&HTLCFailInfo{
Reason: htlcFail,
},
@ -994,7 +994,7 @@ func TestPaymentControlMultiShard(t *testing.T) {
// Assert the failure was recorded.
htlc.failure = &htlcFail
assertPaymentInfo(
t, pControl, info.PaymentHash, info,
t, pControl, info.PaymentIdentifier, info,
firstFailReason, htlc,
)
@ -1003,7 +1003,7 @@ func TestPaymentControlMultiShard(t *testing.T) {
// write a terminal failure to the database without
// syncing.
failReason := FailureReasonPaymentDetails
_, err = pControl.Fail(info.PaymentHash, failReason)
_, err = pControl.Fail(info.PaymentIdentifier, failReason)
if err != nil {
t.Fatalf("unable to fail payment hash: %v", err)
}
@ -1017,10 +1017,10 @@ func TestPaymentControlMultiShard(t *testing.T) {
finalStatus = StatusSucceeded
}
assertPaymentStatus(t, pControl, info.PaymentHash, finalStatus)
assertPaymentStatus(t, pControl, info.PaymentIdentifier, finalStatus)
// Finally assert we cannot register more attempts.
_, err = pControl.RegisterAttempt(info.PaymentHash, &b)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, &b)
require.Equal(t, ErrPaymentTerminal, err)
}
@ -1053,7 +1053,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) {
}
// Init the payment.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
@ -1068,7 +1068,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) {
info.Value, [32]byte{1},
)
_, err = pControl.RegisterAttempt(info.PaymentHash, attempt)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
@ -1077,7 +1077,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) {
b := *attempt
b.AttemptID = 1
b.Route.FinalHop().MPP = nil
_, err = pControl.RegisterAttempt(info.PaymentHash, &b)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrMPPayment {
t.Fatalf("expected ErrMPPayment, got: %v", err)
}
@ -1086,7 +1086,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) {
b.Route.FinalHop().MPP = record.NewMPP(
info.Value, [32]byte{2},
)
_, err = pControl.RegisterAttempt(info.PaymentHash, &b)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrMPPPaymentAddrMismatch {
t.Fatalf("expected ErrMPPPaymentAddrMismatch, got: %v", err)
}
@ -1095,7 +1095,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) {
b.Route.FinalHop().MPP = record.NewMPP(
info.Value/2, [32]byte{1},
)
_, err = pControl.RegisterAttempt(info.PaymentHash, &b)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrMPPTotalAmountMismatch {
t.Fatalf("expected ErrMPPTotalAmountMismatch, got: %v", err)
}
@ -1107,13 +1107,13 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) {
t.Fatalf("unable to generate htlc message: %v", err)
}
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
attempt.Route.FinalHop().MPP = nil
_, err = pControl.RegisterAttempt(info.PaymentHash, attempt)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
@ -1125,7 +1125,7 @@ func TestPaymentControlMPPRecordValidation(t *testing.T) {
info.Value, [32]byte{1},
)
_, err = pControl.RegisterAttempt(info.PaymentHash, &b)
_, err = pControl.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrNonMPPayment {
t.Fatalf("expected ErrNonMPPayment, got: %v", err)
}

43
channeldb/payments.go

@ -216,8 +216,9 @@ func (ps PaymentStatus) String() string {
// PaymentCreationInfo is the information necessary to have ready when
// initiating a payment, moving it into state InFlight.
type PaymentCreationInfo struct {
// PaymentHash is the hash this payment is paying to.
PaymentHash lntypes.Hash
// PaymentIdentifier is the hash this payment is paying to in case of
// non-AMP payments, and the SetID for AMP payments.
PaymentIdentifier lntypes.Hash
// Value is the amount we are paying.
Value lnwire.MilliSatoshi
@ -856,7 +857,7 @@ func fetchSequenceNumbers(paymentBucket kvdb.RBucket) ([][]byte, error) {
func serializePaymentCreationInfo(w io.Writer, c *PaymentCreationInfo) error {
var scratch [8]byte
if _, err := w.Write(c.PaymentHash[:]); err != nil {
if _, err := w.Write(c.PaymentIdentifier[:]); err != nil {
return err
}
@ -886,7 +887,7 @@ func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) {
c := &PaymentCreationInfo{}
if _, err := io.ReadFull(r, c.PaymentHash[:]); err != nil {
if _, err := io.ReadFull(r, c.PaymentIdentifier[:]); err != nil {
return nil, err
}
@ -926,7 +927,20 @@ func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error {
return err
}
return serializeTime(w, a.AttemptTime)
if err := serializeTime(w, a.AttemptTime); err != nil {
return err
}
// If the hash is nil we can just return.
if a.Hash == nil {
return nil
}
if _, err := w.Write(a.Hash[:]); err != nil {
return err
}
return nil
}
func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) {
@ -935,6 +949,7 @@ func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) {
if err != nil {
return nil, err
}
a.Route, err = DeserializeRoute(r)
if err != nil {
return nil, err
@ -945,6 +960,24 @@ func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) {
return nil, err
}
hash := lntypes.Hash{}
_, err = io.ReadFull(r, hash[:])
switch {
// Older payment attempts wouldn't have the hash set, in which case we
// can just return.
case err == io.EOF, err == io.ErrUnexpectedEOF:
return a, nil
case err != nil:
return nil, err
default:
}
a.Hash = &hash
return a, nil
}

41
channeldb/payments_test.go

@ -57,9 +57,11 @@ func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) {
var preimg lntypes.Preimage
copy(preimg[:], rev[:])
hash := preimg.Hash()
c := &PaymentCreationInfo{
PaymentHash: preimg.Hash(),
Value: 1000,
PaymentIdentifier: hash,
Value: 1000,
// Use single second precision to avoid false positive test
// failures due to the monotonic time component.
CreationTime: time.Unix(time.Now().Unix(), 0),
@ -71,6 +73,7 @@ func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) {
SessionKey: priv,
Route: testRoute,
AttemptTime: time.Unix(100, 0),
Hash: &hash,
}
return c, a
}
@ -430,7 +433,7 @@ func TestQueryPayments(t *testing.T) {
}
// Create a new payment entry in the database.
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to initialize "+
"payment in database: %v", err)
@ -439,11 +442,11 @@ func TestQueryPayments(t *testing.T) {
// Immediately delete the payment with index 2.
if i == 1 {
pmt, err := pControl.FetchPayment(
info.PaymentHash,
info.PaymentIdentifier,
)
require.NoError(t, err)
deletePayment(t, db, info.PaymentHash,
deletePayment(t, db, info.PaymentIdentifier,
pmt.SequenceNum)
}
@ -453,13 +456,13 @@ func TestQueryPayments(t *testing.T) {
// duplicate payments will always be succeeded.
if i == (nonDuplicatePayments - 1) {
pmt, err := pControl.FetchPayment(
info.PaymentHash,
info.PaymentIdentifier,
)
require.NoError(t, err)
appendDuplicatePayment(
t, pControl.db,
info.PaymentHash,
info.PaymentIdentifier,
pmt.SequenceNum+1,
preimg,
)
@ -526,12 +529,12 @@ func TestFetchPaymentWithSequenceNumber(t *testing.T) {
require.NoError(t, err)
// Create a new payment entry in the database.
err = pControl.InitPayment(noDuplicates.PaymentHash, noDuplicates)
err = pControl.InitPayment(noDuplicates.PaymentIdentifier, noDuplicates)
require.NoError(t, err)
// Fetch the payment so we can get its sequence nr.
noDuplicatesPayment, err := pControl.FetchPayment(
noDuplicates.PaymentHash,
noDuplicates.PaymentIdentifier,
)
require.NoError(t, err)
@ -540,12 +543,12 @@ func TestFetchPaymentWithSequenceNumber(t *testing.T) {
require.NoError(t, err)
// Create a new payment entry in the database.
err = pControl.InitPayment(hasDuplicates.PaymentHash, hasDuplicates)
err = pControl.InitPayment(hasDuplicates.PaymentIdentifier, hasDuplicates)
require.NoError(t, err)
// Fetch the payment so we can get its sequence nr.
hasDuplicatesPayment, err := pControl.FetchPayment(
hasDuplicates.PaymentHash,
hasDuplicates.PaymentIdentifier,
)
require.NoError(t, err)
@ -558,10 +561,10 @@ func TestFetchPaymentWithSequenceNumber(t *testing.T) {
// Add two duplicates to our second payment.
appendDuplicatePayment(
t, db, hasDuplicates.PaymentHash, duplicateOneSeqNr, preimg,
t, db, hasDuplicates.PaymentIdentifier, duplicateOneSeqNr, preimg,
)
appendDuplicatePayment(
t, db, hasDuplicates.PaymentHash, duplicateTwoSeqNr, preimg,
t, db, hasDuplicates.PaymentIdentifier, duplicateTwoSeqNr, preimg,
)
tests := []struct {
@ -572,37 +575,37 @@ func TestFetchPaymentWithSequenceNumber(t *testing.T) {
}{
{
name: "lookup payment without duplicates",
paymentHash: noDuplicates.PaymentHash,
paymentHash: noDuplicates.PaymentIdentifier,
sequenceNumber: noDuplicatesPayment.SequenceNum,
expectedErr: nil,
},
{
name: "lookup payment with duplicates",
paymentHash: hasDuplicates.PaymentHash,
paymentHash: hasDuplicates.PaymentIdentifier,
sequenceNumber: hasDuplicatesPayment.SequenceNum,
expectedErr: nil,
},
{
name: "lookup first duplicate",
paymentHash: hasDuplicates.PaymentHash,
paymentHash: hasDuplicates.PaymentIdentifier,
sequenceNumber: duplicateOneSeqNr,
expectedErr: nil,
},
{
name: "lookup second duplicate",
paymentHash: hasDuplicates.PaymentHash,
paymentHash: hasDuplicates.PaymentIdentifier,
sequenceNumber: duplicateTwoSeqNr,
expectedErr: nil,
},
{
name: "lookup non-existent duplicate",
paymentHash: hasDuplicates.PaymentHash,
paymentHash: hasDuplicates.PaymentIdentifier,
sequenceNumber: 999999,
expectedErr: ErrDuplicateNotFound,
},
{
name: "lookup duplicate, no duplicates bucket",
paymentHash: noDuplicates.PaymentHash,
paymentHash: noDuplicates.PaymentIdentifier,
sequenceNumber: duplicateTwoSeqNr,
expectedErr: ErrNoDuplicateBucket,
},

51
htlcswitch/switch.go

@ -363,12 +363,15 @@ func (s *Switch) ProcessContractResolution(msg contractcourt.ResolutionMsg) erro
}
// GetPaymentResult returns the the result of the payment attempt with the
// given paymentID. The method returns a channel where the payment result will
// be sent when available, or an error is encountered during forwarding. When a
// result is received on the channel, the HTLC is guaranteed to no longer be in
// flight. The switch shutting down is signaled by closing the channel. If the
// paymentID is unknown, ErrPaymentIDNotFound will be returned.
func (s *Switch) GetPaymentResult(paymentID uint64, paymentHash lntypes.Hash,
// given attemptID. The paymentHash should be set to the payment's overall
// hash, or in case of AMP payments the payment's unique identifier.
//
// The method returns a channel where the payment result will be sent when
// available, or an error is encountered during forwarding. When a result is
// received on the channel, the HTLC is guaranteed to no longer be in flight.
// The switch shutting down is signaled by closing the channel. If the
// attemptID is unknown, ErrPaymentIDNotFound will be returned.
func (s *Switch) GetPaymentResult(attemptID uint64, paymentHash lntypes.Hash,
deobfuscator ErrorDecrypter) (<-chan *PaymentResult, error) {
var (
@ -376,7 +379,7 @@ func (s *Switch) GetPaymentResult(paymentID uint64, paymentHash lntypes.Hash,
err error
outKey = CircuitKey{
ChanID: hop.Source,
HtlcID: paymentID,
HtlcID: attemptID,
}
)
@ -384,7 +387,7 @@ func (s *Switch) GetPaymentResult(paymentID uint64, paymentHash lntypes.Hash,
// result is already available.
// Assumption: no one will add this payment ID other than the caller.
if s.circuits.LookupCircuit(outKey) == nil {
res, err := s.networkResults.getResult(paymentID)
res, err := s.networkResults.getResult(attemptID)
if err != nil {
return nil, err
}
@ -394,7 +397,7 @@ func (s *Switch) GetPaymentResult(paymentID uint64, paymentHash lntypes.Hash,
} else {
// The payment was committed to the circuits, subscribe for a
// result.
nChan, err = s.networkResults.subscribeResult(paymentID)
nChan, err = s.networkResults.subscribeResult(attemptID)
if err != nil {
return nil, err
}
@ -420,12 +423,12 @@ func (s *Switch) GetPaymentResult(paymentID uint64, paymentHash lntypes.Hash,
return
}
log.Debugf("Received network result %T for paymentID=%v", n.msg,
paymentID)
log.Debugf("Received network result %T for attemptID=%v", n.msg,
attemptID)
// Extract the result and pass it to the result channel.
result, err := s.extractResult(
deobfuscator, n, paymentID, paymentHash,
deobfuscator, n, attemptID, paymentHash,
)
if err != nil {
e := fmt.Errorf("unable to extract result: %v", err)
@ -450,10 +453,10 @@ func (s *Switch) CleanStore(keepPids map[uint64]struct{}) error {
}
// SendHTLC is used by other subsystems which aren't belong to htlc switch
// package in order to send the htlc update. The paymentID used MUST be unique
// package in order to send the htlc update. The attemptID used MUST be unique
// for this HTLC, and MUST be used only once, otherwise the switch might reject
// it.
func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, paymentID uint64,
func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, attemptID uint64,
htlc *lnwire.UpdateAddHTLC) error {
// Generate and send new update packet, if error will be received on
@ -461,7 +464,7 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, paymentID uint64,
// system and something wrong happened.
packet := &htlcPacket{
incomingChanID: hop.Source,
incomingHTLCID: paymentID,
incomingHTLCID: attemptID,
outgoingChanID: firstHop,
htlc: htlc,
}
@ -794,7 +797,7 @@ func (s *Switch) getLocalLink(pkt *htlcPacket, htlc *lnwire.UpdateAddHTLC) (
func (s *Switch) handleLocalResponse(pkt *htlcPacket) {
defer s.wg.Done()
paymentID := pkt.incomingHTLCID
attemptID := pkt.incomingHTLCID
// The error reason will be unencypted in case this a local
// failure or a converted error.
@ -807,9 +810,9 @@ func (s *Switch) handleLocalResponse(pkt *htlcPacket) {
// Store the result to the db. This will also notify subscribers about
// the result.
if err := s.networkResults.storeResult(paymentID, n); err != nil {
if err := s.networkResults.storeResult(attemptID, n); err != nil {
log.Errorf("Unable to complete payment for pid=%v: %v",
paymentID, err)
attemptID, err)
return
}
@ -857,7 +860,7 @@ func (s *Switch) handleLocalResponse(pkt *htlcPacket) {
// extractResult uses the given deobfuscator to extract the payment result from
// the given network message.
func (s *Switch) extractResult(deobfuscator ErrorDecrypter, n *networkResult,
paymentID uint64, paymentHash lntypes.Hash) (*PaymentResult, error) {
attemptID uint64, paymentHash lntypes.Hash) (*PaymentResult, error) {
switch htlc := n.msg.(type) {
@ -872,7 +875,7 @@ func (s *Switch) extractResult(deobfuscator ErrorDecrypter, n *networkResult,
// user payment and return fail response.
case *lnwire.UpdateFailHTLC:
paymentErr := s.parseFailedPayment(
deobfuscator, paymentID, paymentHash, n.unencrypted,
deobfuscator, attemptID, paymentHash, n.unencrypted,
n.isResolution, htlc,
)
@ -894,7 +897,7 @@ func (s *Switch) extractResult(deobfuscator ErrorDecrypter, n *networkResult,
// 3) A failure from the remote party, which will need to be decrypted using
// the payment deobfuscator.
func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter,
paymentID uint64, paymentHash lntypes.Hash, unencrypted,
attemptID uint64, paymentHash lntypes.Hash, unencrypted,
isResolution bool, htlc *lnwire.UpdateFailHTLC) error {
switch {
@ -918,7 +921,7 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter,
log.Errorf("%v: (hash=%v, pid=%d): %v",
linkError.FailureDetail.FailureString(),
paymentHash, paymentID, err)
paymentHash, attemptID, err)
return linkError
}
@ -938,7 +941,7 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter,
log.Infof("%v: hash=%v, pid=%d",
linkError.FailureDetail.FailureString(),
paymentHash, paymentID)
paymentHash, attemptID)
return linkError
@ -951,7 +954,7 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter,
if err != nil {
log.Errorf("unable to de-obfuscate onion failure "+
"(hash=%v, pid=%d): %v",
paymentHash, paymentID, err)
paymentHash, attemptID, err)
return ErrUnreadableFailureMessage
}

390
lnrpc/routerrpc/router.pb.go

@ -356,7 +356,10 @@ type SendPaymentRequest struct {
//splitting is necessary. Setting this value will effectively cause lnd to
//split more aggressively, vs only when it thinks it needs to. Note that this
//value is in milli-satoshis.
MaxShardSizeMsat uint64 `protobuf:"varint,21,opt,name=max_shard_size_msat,json=maxShardSizeMsat,proto3" json:"max_shard_size_msat,omitempty"`
MaxShardSizeMsat uint64 `protobuf:"varint,21,opt,name=max_shard_size_msat,json=maxShardSizeMsat,proto3" json:"max_shard_size_msat,omitempty"`
//
//If set, an AMP-payment will be attempted.
Amp bool `protobuf:"varint,22,opt,name=amp,proto3" json:"amp,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -535,6 +538,13 @@ func (m *SendPaymentRequest) GetMaxShardSizeMsat() uint64 {
return 0
}
func (m *SendPaymentRequest) GetAmp() bool {
if m != nil {
return m.Amp
}
return false
}
type TrackPaymentRequest struct {
// The hash of the payment to look up.
PaymentHash []byte `protobuf:"bytes,1,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"`
@ -2485,195 +2495,195 @@ func init() {
func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) }
var fileDescriptor_7a0613f69d37b0a5 = []byte{
// 2997 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x59, 0x4b, 0x77, 0xdb, 0xc8,
0xb1, 0x1e, 0x90, 0x14, 0x45, 0x16, 0x1f, 0x82, 0x5a, 0xb2, 0xc5, 0x4b, 0xf9, 0xa1, 0xc1, 0x3c,
0xcc, 0xeb, 0x3b, 0x23, 0x7b, 0x34, 0xf7, 0xce, 0xcc, 0xbd, 0xf3, 0xb8, 0x43, 0x91, 0x90, 0x05,
0x9b, 0x22, 0x35, 0x4d, 0xca, 0x63, 0x8f, 0x17, 0x08, 0x44, 0x36, 0x45, 0x8c, 0xf0, 0x60, 0x80,
0xa6, 0x6d, 0xcd, 0x2a, 0xc9, 0x2a, 0x27, 0x3f, 0x26, 0xbf, 0x20, 0xe7, 0x24, 0x9b, 0x6c, 0xf2,
0x27, 0xb2, 0xcd, 0x36, 0x9b, 0xac, 0x73, 0xfa, 0x01, 0x10, 0xa0, 0x28, 0xd9, 0x79, 0x6c, 0x24,
0xe0, 0xab, 0xaf, 0xab, 0xab, 0xbb, 0xab, 0xaa, 0x0b, 0x45, 0xb8, 0x19, 0xf8, 0x33, 0x4a, 0x82,
0x60, 0x3a, 0x7c, 0x20, 0x9e, 0x76, 0xa7, 0x81, 0x4f, 0x7d, 0x54, 0x8c, 0xf1, 0x7a, 0x31, 0x98,
0x0e, 0x05, 0xaa, 0xfd, 0x71, 0x15, 0x50, 0x9f, 0x78, 0xa3, 0x63, 0xeb, 0xc2, 0x25, 0x1e, 0xc5,
0xe4, 0xe7, 0x33, 0x12, 0x52, 0x84, 0x20, 0x37, 0x22, 0x21, 0xad, 0x29, 0x3b, 0x4a, 0xa3, 0x8c,
0xf9, 0x33, 0x52, 0x21, 0x6b, 0xb9, 0xb4, 0x96, 0xd9, 0x51, 0x1a, 0x59, 0xcc, 0x1e, 0xd1, 0x7f,
0x40, 0xc1, 0x72, 0xa9, 0xe9, 0x86, 0x16, 0xad, 0x95, 0x39, 0xbc, 0x6a, 0xb9, 0xf4, 0x28, 0xb4,
0x28, 0x7a, 0x17, 0xca, 0x53, 0xa1, 0xd2, 0x9c, 0x58, 0xe1, 0xa4, 0x96, 0xe5, 0x8a, 0x4a, 0x12,
0x3b, 0xb4, 0xc2, 0x09, 0x6a, 0x80, 0x3a, 0xb6, 0x3d, 0xcb, 0x31, 0x87, 0x0e, 0x7d, 0x69, 0x8e,
0x88, 0x43, 0xad, 0x5a, 0x6e, 0x47, 0x69, 0xac, 0xe0, 0x2a, 0xc7, 0x5b, 0x0e, 0x7d, 0xd9, 0x66,
0x68, 0x52, 0x99, 0x35, 0x1a, 0x05, 0xb5, 0xcd, 0x94, 0xb2, 0xe6, 0x68, 0x14, 0xa0, 0x7b, 0xb0,
0x16, 0x51, 0x02, 0xb1, 0x86, 0xda, 0xca, 0x8e, 0xd2, 0x28, 0xe2, 0xea, 0x34, 0xbd, 0xb2, 0x7b,
0xb0, 0x46, 0x6d, 0x97, 0xf8, 0x33, 0x6a, 0x86, 0x64, 0xe8, 0x7b, 0xa3, 0xb0, 0x96, 0x17, 0x93,
0x4a, 0xb8, 0x2f, 0x50, 0xa4, 0x41, 0x65, 0x4c, 0x88, 0xe9, 0xd8, 0xae, 0x4d, 0x4d, 0xb6, 0xc2,
0x55, 0xbe, 0xc2, 0xd2, 0x98, 0x90, 0x0e, 0xc3, 0xfa, 0x16, 0x45, 0xef, 0x43, 0x75, 0xce, 0xe1,
0xdb, 0x50, 0xe1, 0xa4, 0x72, 0x44, 0xe2, 0x7b, 0xb1, 0x0b, 0xaa, 0x3f, 0xa3, 0x67, 0xbe, 0xed,
0x9d, 0x99, 0xc3, 0x89, 0xe5, 0x99, 0xf6, 0xa8, 0x56, 0xd8, 0x51, 0x1a, 0xb9, 0xfd, 0x5c, 0x4d,
0x79, 0xa8, 0xe0, 0x6a, 0x24, 0x6d, 0x4d, 0x2c, 0xcf, 0x18, 0xa1, 0xfb, 0xb0, 0xbe, 0xc8, 0x0f,
0x6b, 0x1b, 0x3b, 0xd9, 0x46, 0x0e, 0xaf, 0xa5, 0xa9, 0x21, 0xfa, 0x10, 0xd6, 0x1c, 0x2b, 0xa4,
0xe6, 0xc4, 0x9f, 0x9a, 0xd3, 0xd9, 0xe9, 0x39, 0xb9, 0xa8, 0x55, 0xf9, 0xee, 0x54, 0x18, 0x7c,
0xe8, 0x4f, 0x8f, 0x39, 0x88, 0x6e, 0x03, 0xf0, 0x6d, 0xe6, 0xa6, 0xd6, 0x8a, 0x7c, 0xc5, 0x45,
0x86, 0x70, 0x33, 0xd1, 0x27, 0x50, 0xe2, 0xee, 0x61, 0x4e, 0x6c, 0x8f, 0x86, 0x35, 0xd8, 0xc9,
0x36, 0x4a, 0x7b, 0xea, 0xae, 0xe3, 0x31, 0x4f, 0xc1, 0x4c, 0x72, 0x68, 0x7b, 0x14, 0x43, 0x10,
0x3d, 0x86, 0x68, 0x04, 0x1b, 0xcc, 0x2d, 0xcc, 0xe1, 0x2c, 0xa4, 0xbe, 0x6b, 0x06, 0x64, 0xe8,
0x07, 0xa3, 0xb0, 0x56, 0xe2, 0x43, 0xff, 0x7b, 0x37, 0xf6, 0xb6, 0xdd, 0xcb, 0xee, 0xb5, 0xdb,
0x26, 0x21, 0x6d, 0xf1, 0x71, 0x58, 0x0c, 0xd3, 0x3d, 0x1a, 0x5c, 0xe0, 0xf5, 0xd1, 0x22, 0x8e,
0x3e, 0x02, 0x64, 0x39, 0x8e, 0xff, 0xca, 0x0c, 0x89, 0x33, 0x36, 0xe5, 0x59, 0xd6, 0xd6, 0x76,
0x94, 0x46, 0x01, 0xab, 0x5c, 0xd2, 0x27, 0xce, 0x58, 0xaa, 0x47, 0x9f, 0x41, 0x85, 0xdb, 0x34,
0x26, 0x16, 0x9d, 0x05, 0x24, 0xac, 0xa9, 0x3b, 0xd9, 0x46, 0x75, 0x6f, 0x5d, 0x2e, 0xe4, 0x40,
0xc0, 0xfb, 0x36, 0xc5, 0x65, 0xc6, 0x93, 0xef, 0x21, 0xda, 0x86, 0xa2, 0x6b, 0xbd, 0x36, 0xa7,
0x56, 0x40, 0xc3, 0xda, 0xfa, 0x8e, 0xd2, 0xa8, 0xe0, 0x82, 0x6b, 0xbd, 0x3e, 0x66, 0xef, 0x68,
0x17, 0x36, 0x3c, 0xdf, 0xb4, 0xbd, 0xb1, 0x63, 0x9f, 0x4d, 0xa8, 0x39, 0x9b, 0x8e, 0x2c, 0x4a,
0xc2, 0x1a, 0xe2, 0x36, 0xac, 0x7b, 0xbe, 0x21, 0x25, 0x27, 0x42, 0x80, 0x3e, 0x86, 0x0d, 0xa6,
0x2c, 0x9c, 0x58, 0xc1, 0xc8, 0x0c, 0xed, 0x9f, 0x88, 0xf0, 0x8c, 0x1b, 0xec, 0xc4, 0xb1, 0xea,
0x5a, 0xaf, 0xfb, 0x4c, 0xd2, 0xb7, 0x7f, 0x22, 0xcc, 0x3b, 0xea, 0x6d, 0xb8, 0xb9, 0x7c, 0x3b,
0x58, 0xc0, 0xb1, 0xf3, 0x54, 0xf8, 0x40, 0xf6, 0x88, 0x36, 0x61, 0xe5, 0xa5, 0xe5, 0xcc, 0x08,
0x0f, 0xc2, 0x32, 0x16, 0x2f, 0xff, 0x97, 0xf9, 0x42, 0xd1, 0x26, 0xb0, 0x31, 0x08, 0xac, 0xe1,
0xf9, 0x42, 0x1c, 0x2f, 0x86, 0xa1, 0x72, 0x39, 0x0c, 0xaf, 0x58, 0x5e, 0xe6, 0x8a, 0xe5, 0x69,
0xdf, 0xc0, 0x1a, 0x77, 0x88, 0x03, 0x42, 0xae, 0xcb, 0x16, 0x5b, 0xc0, 0x72, 0x01, 0x0f, 0x1c,
0x91, 0x31, 0xf2, 0x96, 0xcb, 0x62, 0x46, 0x1b, 0x81, 0x3a, 0x1f, 0x1f, 0x4e, 0x7d, 0x2f, 0x24,
0x2c, 0x15, 0x30, 0x7f, 0x61, 0x0e, 0xcf, 0xe2, 0x89, 0xef, 0x97, 0xc2, 0x47, 0x55, 0x25, 0x7e,
0x40, 0xf8, 0x6e, 0x31, 0x7f, 0x67, 0x71, 0x6a, 0x3a, 0xfe, 0xf0, 0x9c, 0xe5, 0x0c, 0xeb, 0x42,
0xaa, 0xaf, 0x30, 0xb8, 0xe3, 0x0f, 0xcf, 0xdb, 0x0c, 0xd4, 0x5e, 0x88, 0xb4, 0x36, 0xf0, 0xf9,
0x5c, 0xff, 0xc0, 0x76, 0x68, 0xb0, 0xc2, 0x5d, 0x97, 0xab, 0x2d, 0xed, 0x95, 0x93, 0x31, 0x80,
0x85, 0x48, 0x7b, 0x01, 0x1b, 0x29, 0xe5, 0x72, 0x15, 0x75, 0x28, 0x4c, 0x03, 0x62, 0xbb, 0xd6,
0x19, 0x91, 0x9a, 0xe3, 0x77, 0xd4, 0x80, 0xd5, 0xb1, 0x65, 0x3b, 0xb3, 0x20, 0x52, 0x5c, 0x8d,
0x7c, 0x52, 0xa0, 0x38, 0x12, 0x6b, 0xb7, 0xa0, 0x8e, 0x49, 0x48, 0xe8, 0x91, 0x1d, 0x86, 0xb6,
0xef, 0xb5, 0x7c, 0x8f, 0x06, 0xbe, 0x23, 0x57, 0xa0, 0xdd, 0x86, 0xed, 0xa5, 0x52, 0x61, 0x02,
0x1b, 0xfc, 0xdd, 0x8c, 0x04, 0x17, 0xcb, 0x07, 0x7f, 0x07, 0xdb, 0x4b, 0xa5, 0xd2, 0xfe, 0x8f,
0x60, 0x65, 0x6a, 0xd9, 0x01, 0x3b, 0x7b, 0x16, 0xc3, 0x37, 0x13, 0x31, 0x7c, 0x6c, 0xd9, 0xc1,
0xa1, 0x1d, 0x52, 0x3f, 0xb8, 0xc0, 0x82, 0xf4, 0x38, 0x57, 0x50, 0xd4, 0x8c, 0xd6, 0x81, 0x5b,
0xcf, 0x0c, 0x77, 0xea, 0x07, 0xcb, 0xed, 0x9d, 0xeb, 0x54, 0xde, 0x42, 0xa7, 0x76, 0x17, 0x6e,
0x5f, 0xa1, 0x4d, 0xae, 0xef, 0x37, 0x0a, 0x94, 0x12, 0xe3, 0x58, 0xe0, 0x7a, 0xfe, 0x88, 0x98,
0xe3, 0xc0, 0x77, 0xa3, 0x3d, 0x67, 0xc0, 0x41, 0xe0, 0xbb, 0xcc, 0x05, 0xb9, 0x90, 0xfa, 0x32,
0x5e, 0xf2, 0xec, 0x75, 0xe0, 0xa3, 0x8f, 0x61, 0x75, 0x22, 0x14, 0xf0, 0xa4, 0x5e, 0xda, 0xdb,
0x58, 0x30, 0xab, 0x6d, 0x51, 0x0b, 0x47, 0x9c, 0xc7, 0xb9, 0x42, 0x56, 0xcd, 0x3d, 0xce, 0x15,
0x72, 0xea, 0xca, 0xe3, 0x5c, 0x61, 0x45, 0xcd, 0x3f, 0xce, 0x15, 0xf2, 0xea, 0xaa, 0xf6, 0x17,
0x05, 0x0a, 0x11, 0x9b, 0x59, 0xc2, 0x4e, 0xd0, 0x64, 0x6e, 0x28, 0x7d, 0xb7, 0xc0, 0x80, 0x81,
0xed, 0x12, 0xb4, 0x03, 0x65, 0x2e, 0x4c, 0x47, 0x04, 0x30, 0xac, 0xc9, 0xa3, 0x82, 0xdf, 0x36,
0x11, 0x83, 0xbb, 0x7f, 0x4e, 0xde, 0x36, 0x82, 0x12, 0xdd, 0xa9, 0xe1, 0x6c, 0x38, 0x24, 0x61,
0x28, 0x66, 0x59, 0x11, 0x14, 0x89, 0xf1, 0x89, 0x3e, 0x84, 0xb5, 0x88, 0x12, 0xcd, 0x95, 0x17,
0xe1, 0x21, 0x61, 0x39, 0x5d, 0x03, 0xd4, 0x24, 0xcf, 0x9d, 0xdf, 0x6f, 0xd5, 0x39, 0x91, 0x4d,
0x2a, 0x16, 0xaf, 0xed, 0xc0, 0x9d, 0x47, 0x8b, 0x4e, 0xd7, 0xf2, 0xbd, 0xb1, 0x7d, 0x16, 0xf9,
0xd6, 0x0f, 0x70, 0xf7, 0x4a, 0x86, 0xf4, 0xaf, 0xcf, 0x21, 0x3f, 0xe4, 0x08, 0xdf, 0x9f, 0xd2,
0xde, 0xdd, 0xc4, 0xae, 0x2f, 0x1d, 0x28, 0xe9, 0xda, 0x73, 0xb8, 0xd3, 0xbf, 0x76, 0xf6, 0x7f,
0x5e, 0xf5, 0xbb, 0x70, 0xb7, 0x7f, 0xbd, 0xd9, 0xda, 0x2f, 0x32, 0xb0, 0xb9, 0x8c, 0xc0, 0xee,
0xe9, 0x89, 0xe5, 0x8c, 0x4d, 0xc7, 0x1e, 0x93, 0xb8, 0x98, 0x10, 0xd9, 0x7a, 0x8d, 0x09, 0x3a,
0xf6, 0x98, 0x44, 0xd5, 0xc4, 0x3d, 0x58, 0xe3, 0x57, 0x74, 0xe0, 0x9f, 0x5a, 0xa7, 0xb6, 0x63,
0x53, 0x91, 0xb7, 0x32, 0xb8, 0x3a, 0xf1, 0xa7, 0xc7, 0x73, 0x14, 0xdd, 0x84, 0xfc, 0x2b, 0xc2,
0xf2, 0x2d, 0x2f, 0x99, 0x32, 0x58, 0xbe, 0xa1, 0xcf, 0x60, 0xcb, 0xb5, 0x5e, 0xdb, 0xee, 0xcc,
0x35, 0xe7, 0x85, 0x4e, 0x38, 0x73, 0x68, 0xc8, 0x5d, 0xa5, 0x82, 0x6f, 0x48, 0x71, 0x7c, 0x03,
0x70, 0x21, 0x6a, 0xc1, 0x1d, 0xd7, 0xf6, 0xf8, 0x38, 0x99, 0x61, 0xcc, 0x80, 0x38, 0xd6, 0x6b,
0xd3, 0xf6, 0x28, 0x09, 0x5e, 0x5a, 0x0e, 0x77, 0xa3, 0x1c, 0xde, 0x96, 0xac, 0x28, 0x1f, 0x31,
0x8e, 0x21, 0x29, 0xda, 0x8f, 0xb0, 0xc5, 0x13, 0x47, 0xc2, 0xd0, 0x68, 0xe7, 0x99, 0xdf, 0x07,
0xbe, 0x6b, 0xb2, 0xd0, 0x8a, 0x22, 0x90, 0x01, 0x5d, 0x7f, 0x44, 0x58, 0x04, 0x52, 0x5f, 0x88,
0x64, 0x04, 0x52, 0x9f, 0x0b, 0x92, 0x95, 0x63, 0x36, 0x55, 0x39, 0x6a, 0xe7, 0x50, 0xbb, 0x3c,
0x97, 0xf4, 0xa0, 0x1d, 0x28, 0x25, 0x77, 0x90, 0x4d, 0xa7, 0xe0, 0x24, 0x94, 0x0c, 0xed, 0xcc,
0x9b, 0x43, 0x5b, 0xfb, 0x93, 0x02, 0xeb, 0xfb, 0x33, 0xdb, 0x19, 0xa5, 0xae, 0x89, 0xa4, 0x75,
0x4a, 0xba, 0xae, 0x5d, 0x56, 0xb4, 0x66, 0x96, 0x16, 0xad, 0x1f, 0x2d, 0xa9, 0xfa, 0xb2, 0xbc,
0xea, 0xcb, 0x2c, 0xa9, 0xf9, 0xee, 0x42, 0x69, 0x5e, 0xc2, 0xb1, 0x23, 0xcd, 0x36, 0xca, 0x18,
0x26, 0x51, 0xfd, 0x16, 0x5e, 0xaa, 0x81, 0x57, 0x2e, 0xd5, 0xc0, 0xda, 0x17, 0x80, 0x92, 0x6b,
0x91, 0x7b, 0x16, 0x5f, 0x68, 0xca, 0xd5, 0x17, 0xda, 0x2d, 0xa8, 0xf7, 0x67, 0xa7, 0xe1, 0x30,
0xb0, 0x4f, 0xc9, 0x21, 0x75, 0x86, 0xfa, 0x4b, 0xe2, 0xd1, 0x30, 0x0a, 0xed, 0xbf, 0xe5, 0xa0,
0x18, 0xa3, 0xac, 0x5e, 0xb0, 0xbd, 0xa1, 0xef, 0x46, 0xeb, 0xf2, 0x88, 0xc3, 0x96, 0x26, 0xfc,
0x7e, 0x3d, 0x12, 0xb5, 0x84, 0xc4, 0x18, 0x31, 0x7e, 0x6a, 0x1f, 0x24, 0x3f, 0x23, 0xf8, 0xc9,
0x6d, 0x10, 0xfc, 0x06, 0xa8, 0xb1, 0xfe, 0x09, 0x75, 0x86, 0xf1, 0xbe, 0xe1, 0x6a, 0x84, 0x33,
0x63, 0x04, 0x33, 0xd6, 0x1c, 0x31, 0x73, 0x82, 0x19, 0xe1, 0x92, 0xf9, 0x2e, 0x94, 0x59, 0xc6,
0x0c, 0xa9, 0xe5, 0x4e, 0x4d, 0x2f, 0x94, 0x2e, 0x5f, 0x8a, 0xb1, 0x6e, 0x88, 0xbe, 0x06, 0x20,
0x6c, 0x7d, 0x26, 0xbd, 0x98, 0x12, 0x9e, 0x34, 0xab, 0x7b, 0x77, 0x12, 0xbe, 0x13, 0x6f, 0xc0,
0x2e, 0xff, 0x3b, 0xb8, 0x98, 0x12, 0x5c, 0x24, 0xd1, 0x23, 0xfa, 0x06, 0x2a, 0x63, 0x3f, 0x78,
0xc5, 0x4a, 0x3e, 0x0e, 0xca, 0x8b, 0x65, 0x2b, 0xa1, 0xe1, 0x40, 0xc8, 0xf9, 0xf0, 0xc3, 0x77,
0x70, 0x79, 0x9c, 0x78, 0x47, 0x4f, 0x00, 0x45, 0xe3, 0xf9, 0x3d, 0x20, 0x94, 0x14, 0xb8, 0x92,
0xed, 0xcb, 0x4a, 0x58, 0x94, 0x46, 0x8a, 0xd4, 0xf1, 0x02, 0x86, 0xbe, 0x84, 0x72, 0x48, 0x28,
0x75, 0x88, 0x54, 0x53, 0xe4, 0x6a, 0x6e, 0xa6, 0x6a, 0x72, 0x26, 0x8e, 0x34, 0x94, 0xc2, 0xf9,
0x2b, 0xda, 0x87, 0x35, 0xc7, 0xf6, 0xce, 0x93, 0x66, 0x00, 0x1f, 0x5f, 0x4b, 0x8c, 0xef, 0xd8,
0xde, 0x79, 0xd2, 0x86, 0x8a, 0x93, 0x04, 0xb4, 0xaf, 0xa0, 0x18, 0xef, 0x12, 0x2a, 0xc1, 0xea,
0x49, 0xf7, 0x49, 0xb7, 0xf7, 0x7d, 0x57, 0x7d, 0x07, 0x15, 0x20, 0xd7, 0xd7, 0xbb, 0x6d, 0x55,
0x61, 0x30, 0xd6, 0x5b, 0xba, 0xf1, 0x54, 0x57, 0x33, 0xec, 0xe5, 0xa0, 0x87, 0xbf, 0x6f, 0xe2,
0xb6, 0x9a, 0xdd, 0x5f, 0x85, 0x15, 0x3e, 0xaf, 0xf6, 0x3b, 0x05, 0x0a, 0xfc, 0x04, 0xbd, 0xb1,
0x8f, 0xfe, 0x0b, 0x62, 0xe7, 0xe2, 0xd7, 0x1f, 0xab, 0x00, 0xb9, 0xd7, 0x55, 0x70, 0xec, 0x30,
0x03, 0x89, 0x33, 0x72, 0xec, 0x1a, 0x31, 0x39, 0x23, 0xc8, 0x91, 0x20, 0x26, 0xdf, 0x4f, 0x68,
0x4e, 0x65, 0xa5, 0x1c, 0x5e, 0x8b, 0x04, 0xd1, 0x1d, 0x9c, 0xfc, 0x36, 0x4b, 0xdd, 0xd5, 0x89,
0x6f, 0x33, 0xc9, 0xd5, 0x3e, 0x87, 0x72, 0xf2, 0xcc, 0xd1, 0x3d, 0xc8, 0xd9, 0xde, 0xd8, 0x97,
0x81, 0xb8, 0xb1, 0xe0, 0x5c, 0x6c, 0x91, 0x98, 0x13, 0x34, 0x04, 0xea, 0xe2, 0x39, 0x6b, 0x15,
0x28, 0x25, 0x0e, 0x4d, 0xfb, 0xb3, 0x02, 0x95, 0xd4, 0x21, 0xbc, 0xb5, 0x76, 0xf4, 0x35, 0x94,
0x5f, 0xd9, 0x01, 0x31, 0x93, 0xf5, 0x68, 0x75, 0xaf, 0x9e, 0xae, 0x47, 0xa3, 0xff, 0x2d, 0x7f,
0x44, 0x70, 0x89, 0xf1, 0x25, 0x80, 0xfe, 0x1f, 0xaa, 0xd1, 0x45, 0x32, 0x22, 0xd4, 0xb2, 0x1d,
0xbe, 0x55, 0xd5, 0x94, 0x7b, 0x48, 0x6e, 0x9b, 0xcb, 0x71, 0x65, 0x9c, 0x7c, 0x45, 0x1f, 0xcc,
0x15, 0x84, 0x34, 0xb0, 0xbd, 0x33, 0xbe, 0x7f, 0xc5, 0x98, 0xd6, 0xe7, 0x20, 0x2b, 0xf5, 0x2a,
0xf2, 0x2e, 0xeb, 0x53, 0x8b, 0xce, 0xd8, 0x87, 0xd5, 0x4a, 0x48, 0x2d, 0x99, 0xc9, 0xaa, 0xa9,
0xd8, 0x4a, 0x10, 0x09, 0x16, 0xac, 0x54, 0x39, 0x9e, 0xb9, 0x54, 0x8e, 0xaf, 0xb0, 0x8c, 0x21,
0x12, 0x6d, 0x69, 0x0f, 0xc9, 0xc5, 0x1f, 0x0e, 0x3a, 0xad, 0x26, 0xa5, 0xc4, 0x9d, 0x52, 0x2c,
0x08, 0xb2, 0xfe, 0xf9, 0x06, 0xa0, 0x65, 0x07, 0xc3, 0x99, 0x4d, 0x9f, 0x90, 0x0b, 0x76, 0xad,
0x45, 0x19, 0x5d, 0xa4, 0xbd, 0xfc, 0x50, 0x64, 0xf1, 0x2d, 0x58, 0x8d, 0x12, 0x91, 0xc8, 0x6f,
0xf9, 0x09, 0x4f, 0x40, 0xda, 0xef, 0x73, 0xb0, 0x2d, 0x8f, 0x54, 0x9c, 0x06, 0x25, 0xc1, 0x90,
0x4c, 0xe3, 0xef, 0xb4, 0x47, 0xb0, 0x39, 0x4f, 0xaa, 0x62, 0x22, 0x33, 0xfa, 0xf6, 0x2b, 0xed,
0xdd, 0x48, 0xac, 0x74, 0x6e, 0x06, 0x46, 0x71, 0xb2, 0x9d, 0x9b, 0xf6, 0x30, 0xa1, 0xc8, 0x72,
0xfd, 0x99, 0x27, 0x5d, 0x54, 0x64, 0x3c, 0x34, 0x77, 0x67, 0x26, 0xe2, 0x1e, 0x7d, 0x0f, 0x62,
0x27, 0x37, 0xc9, 0xeb, 0xa9, 0x1d, 0x5c, 0xf0, 0xec, 0x57, 0x99, 0xa7, 0x5b, 0x9d, 0xa3, 0x97,
0x3e, 0x9e, 0x32, 0x97, 0x3f, 0x9e, 0xbe, 0x84, 0x7a, 0x1c, 0x1d, 0xb2, 0x0d, 0x43, 0x46, 0xf1,
0xed, 0xb7, 0xca, 0x6d, 0xd8, 0x8a, 0x18, 0x38, 0x22, 0xc8, 0x2b, 0xf0, 0x21, 0x6c, 0x26, 0x42,
0x6b, 0x6e, 0xba, 0x88, 0x44, 0x34, 0x8f, 0xae, 0xa4, 0xe9, 0xf1, 0x08, 0x69, 0xba, 0xa8, 0x85,
0xe2, 0xfc, 0x2f, 0x4d, 0xff, 0x19, 0x54, 0x17, 0xda, 0x14, 0x05, 0x7e, 0xee, 0xff, 0x7b, 0x39,
0xb3, 0x2e, 0x3b, 0x9e, 0xdd, 0x25, 0xbd, 0x8a, 0xca, 0x30, 0xd5, 0xa7, 0xb8, 0x0d, 0xe0, 0x7b,
0xb6, 0xef, 0x99, 0xa7, 0x8e, 0x7f, 0xca, 0x13, 0x6e, 0x19, 0x17, 0x39, 0xb2, 0xef, 0xf8, 0xa7,
0xf5, 0x6f, 0x01, 0xfd, 0x8b, 0x1f, 0xf8, 0x7f, 0x50, 0xe0, 0xd6, 0x72, 0x13, 0xe5, 0x3d, 0xff,
0x6f, 0x73, 0xa1, 0x2f, 0x21, 0x6f, 0x0d, 0xa9, 0xed, 0x7b, 0x32, 0x33, 0xbc, 0x97, 0x18, 0x8a,
0x49, 0xe8, 0x3b, 0x2f, 0xc9, 0xa1, 0xef, 0x8c, 0xa4, 0x31, 0x4d, 0x4e, 0xc5, 0x72, 0x48, 0x2a,
0xe8, 0xb2, 0xe9, 0xa0, 0xd3, 0x7e, 0xa5, 0xc0, 0x96, 0xe8, 0x22, 0xb0, 0x13, 0x17, 0x41, 0x1d,
0x05, 0xc0, 0x1e, 0x00, 0x77, 0x93, 0xa9, 0x6f, 0x7b, 0x34, 0xce, 0x61, 0x22, 0x2a, 0x65, 0x6d,
0x70, 0xcc, 0x44, 0xb8, 0xc8, 0x68, 0xfc, 0x11, 0x7d, 0xba, 0x60, 0x68, 0xf2, 0x9e, 0x9c, 0xcf,
0x90, 0x36, 0x50, 0xab, 0x43, 0xed, 0xb2, 0x0d, 0x62, 0x0b, 0xef, 0xff, 0x32, 0x07, 0x95, 0x54,
0xea, 0x4a, 0xdf, 0x5d, 0x15, 0x28, 0x76, 0x7b, 0x66, 0x5b, 0x1f, 0x34, 0x8d, 0x8e, 0xaa, 0x20,
0x15, 0xca, 0xbd, 0xae, 0xd1, 0xeb, 0x9a, 0x6d, 0xbd, 0xd5, 0x6b, 0xb3, 0x5b, 0xec, 0x06, 0xac,
0x77, 0x8c, 0xee, 0x13, 0xb3, 0xdb, 0x1b, 0x98, 0x7a, 0xc7, 0x78, 0x64, 0xec, 0x77, 0x74, 0x35,
0x8b, 0x36, 0x41, 0xed, 0x75, 0xcd, 0xd6, 0x61, 0xd3, 0xe8, 0x9a, 0x03, 0xe3, 0x48, 0xef, 0x9d,
0x0c, 0xd4, 0x1c, 0x43, 0x59, 0xba, 0x31, 0xf5, 0x67, 0x2d, 0x5d, 0x6f, 0xf7, 0xcd, 0xa3, 0xe6,
0x33, 0x75, 0x05, 0xd5, 0x60, 0xd3, 0xe8, 0xf6, 0x4f, 0x0e, 0x0e, 0x8c, 0x96, 0xa1, 0x77, 0x07,
0xe6, 0x7e, 0xb3, 0xd3, 0xec, 0xb6, 0x74, 0x35, 0x8f, 0x6e, 0x02, 0x32, 0xba, 0xad, 0xde, 0xd1,
0x71, 0x47, 0x1f, 0xe8, 0x66, 0x74, 0x5b, 0xae, 0xa2, 0x0d, 0x58, 0xe3, 0x7a, 0x9a, 0xed, 0xb6,
0x79, 0xd0, 0x34, 0x3a, 0x7a, 0x5b, 0x2d, 0x30, 0x4b, 0x24, 0xa3, 0x6f, 0xb6, 0x8d, 0x7e, 0x73,
0x9f, 0xc1, 0x45, 0x36, 0xa7, 0xd1, 0x7d, 0xda, 0x33, 0x5a, 0xba, 0xd9, 0x62, 0x6a, 0x19, 0x0a,
0x8c, 0x1c, 0xa1, 0x27, 0xdd, 0xb6, 0x8e, 0x8f, 0x9b, 0x46, 0x5b, 0x2d, 0xa1, 0x6d, 0xd8, 0x8a,
0x60, 0xfd, 0xd9, 0xb1, 0x81, 0x9f, 0x9b, 0x83, 0x5e, 0xcf, 0xec, 0xf7, 0x7a, 0x5d, 0xb5, 0x9c,
0xd4, 0xc4, 0x56, 0xdb, 0x3b, 0xd6, 0xbb, 0x6a, 0x05, 0x6d, 0xc1, 0xc6, 0xd1, 0xf1, 0xb1, 0x19,
0x49, 0xa2, 0xc5, 0x56, 0x19, 0xbd, 0xd9, 0x6e, 0x63, 0xbd, 0xdf, 0x37, 0x8f, 0x8c, 0xfe, 0x51,
0x73, 0xd0, 0x3a, 0x54, 0xd7, 0xd8, 0x92, 0xfa, 0xfa, 0xc0, 0x1c, 0xf4, 0x06, 0xcd, 0xce, 0x1c,
0x57, 0x99, 0x41, 0x73, 0x9c, 0x4d, 0xda, 0xe9, 0x7d, 0xaf, 0xae, 0xb3, 0x0d, 0x67, 0x70, 0xef,
0xa9, 0x34, 0x11, 0xb1, 0xb5, 0xcb, 0xe3, 0x89, 0xe6, 0x54, 0x37, 0x18, 0x68, 0x74, 0x9f, 0x36,
0x3b, 0x46, 0xdb, 0x7c, 0xa2, 0x3f, 0xe7, 0xd5, 0xc6, 0x26, 0x03, 0x85, 0x65, 0xe6, 0x31, 0xee,
0x3d, 0x62, 0x86, 0xa8, 0x37, 0x10, 0x82, 0x6a, 0xcb, 0xc0, 0xad, 0x93, 0x4e, 0x13, 0x9b, 0xb8,
0x77, 0x32, 0xd0, 0xd5, 0x9b, 0xf7, 0x7f, 0xab, 0x40, 0x39, 0x79, 0x9b, 0xb0, 0x53, 0x37, 0xba,
0xe6, 0x41, 0xc7, 0x78, 0x74, 0x38, 0x10, 0x4e, 0xd0, 0x3f, 0x69, 0xb1, 0x23, 0xd3, 0x59, 0x15,
0x83, 0xa0, 0x2a, 0x36, 0x3d, 0x5e, 0x6c, 0x86, 0xcd, 0x25, 0xb1, 0x6e, 0x4f, 0xea, 0xcd, 0x32,
0xe3, 0x25, 0xa8, 0x63, 0xdc, 0xc3, 0x6a, 0x0e, 0xbd, 0x0f, 0x3b, 0x12, 0x61, 0xe7, 0x8a, 0xb1,
0xde, 0x1a, 0x98, 0xc7, 0xcd, 0xe7, 0x47, 0xec, 0xd8, 0x85, 0x93, 0xf5, 0xd5, 0x15, 0x74, 0x17,
0xb6, 0x63, 0xd6, 0x32, 0xbf, 0xb8, 0xff, 0x15, 0xd4, 0xae, 0x8a, 0x4a, 0x04, 0x90, 0xef, 0xeb,
0x83, 0x41, 0x47, 0x17, 0x95, 0xd7, 0x81, 0x70, 0x5c, 0x80, 0x3c, 0xd6, 0xfb, 0x27, 0x47, 0xba,
0x9a, 0xb9, 0xff, 0x3f, 0xa0, 0x2e, 0x86, 0x0a, 0x93, 0xeb, 0x5d, 0xe6, 0x32, 0xea, 0x3b, 0x2c,
0x00, 0xa4, 0xff, 0xa8, 0x0a, 0x53, 0xd1, 0x3c, 0x19, 0xf4, 0xd4, 0xcc, 0xde, 0x5f, 0x4b, 0x90,
0xe7, 0x5f, 0x10, 0x01, 0xfa, 0x16, 0x2a, 0x89, 0x0e, 0xef, 0xd3, 0x3d, 0x74, 0xfb, 0xda, 0xde,
0x6f, 0x3d, 0x6a, 0x7c, 0x49, 0xf8, 0xa1, 0x82, 0xf6, 0xa1, 0x9a, 0xec, 0x5d, 0x3e, 0xdd, 0x43,
0xc9, 0xc2, 0x7b, 0x49, 0x5b, 0x73, 0x89, 0x8e, 0x27, 0xa0, 0xea, 0x21, 0xb5, 0x5d, 0x76, 0xff,
0xcb, 0xee, 0x22, 0xaa, 0x27, 0x13, 0x57, 0xba, 0x65, 0x59, 0xdf, 0x5e, 0x2a, 0x93, 0xa9, 0xf4,
0x3b, 0x56, 0x6b, 0xc5, 0xfd, 0xbd, 0x4b, 0x0b, 0x4a, 0x37, 0x15, 0xeb, 0x77, 0xae, 0x12, 0xcb,
0xfe, 0x41, 0xf6, 0xd7, 0x19, 0xb6, 0xc6, 0x4a, 0x42, 0xb6, 0x64, 0x97, 0x16, 0x94, 0x2e, 0xa9,
0x48, 0xd0, 0x08, 0x36, 0x96, 0xf4, 0xfe, 0xd0, 0x07, 0xe9, 0xfc, 0x7c, 0x45, 0xe7, 0xb0, 0xfe,
0xe1, 0x9b, 0x68, 0x72, 0xf1, 0x23, 0xd8, 0x58, 0xd2, 0x24, 0x4c, 0xcd, 0x72, 0x75, 0x8b, 0x31,
0x35, 0xcb, 0x75, 0xbd, 0xc6, 0x1f, 0xe1, 0xc6, 0xd2, 0x4e, 0x1f, 0xba, 0x97, 0x50, 0x70, 0x5d,
0x67, 0xb1, 0xde, 0x78, 0x33, 0x51, 0xce, 0x35, 0x85, 0xad, 0x2b, 0x5a, 0x53, 0xe8, 0x3f, 0x13,
0x4a, 0xae, 0x6f, 0x70, 0xd5, 0xef, 0xbf, 0x0d, 0x75, 0x3e, 0x63, 0xff, 0x2d, 0x66, 0xec, 0xbf,
0xfd, 0x8c, 0x6f, 0x68, 0x52, 0xa1, 0x17, 0xa0, 0x2e, 0x76, 0x4d, 0x90, 0xb6, 0x78, 0x16, 0x97,
0xdb, 0x37, 0xf5, 0xf7, 0xae, 0xe5, 0x48, 0xe5, 0x06, 0xc0, 0xbc, 0xb1, 0x80, 0x6e, 0x25, 0x86,
0x5c, 0xea, 0x9d, 0xd4, 0x6f, 0x5f, 0x21, 0x95, 0xaa, 0x06, 0xb0, 0xb1, 0xa4, 0xd3, 0x90, 0xf2,
0xae, 0xab, 0x3b, 0x11, 0xf5, 0xcd, 0x65, 0x1f, 0xe4, 0x0f, 0x15, 0x74, 0x24, 0x02, 0x36, 0xfa,
0x19, 0xe8, 0x0d, 0x19, 0xa8, 0xb6, 0xfc, 0xc3, 0x61, 0x16, 0xf2, 0x50, 0x7d, 0xa8, 0xa0, 0x1e,
0x94, 0x93, 0x59, 0xe7, 0x8d, 0xe9, 0xe8, 0x8d, 0x0a, 0xc7, 0xb0, 0x96, 0x2a, 0xda, 0xfc, 0x20,
0xe5, 0xe7, 0xd7, 0xd5, 0x75, 0xa9, 0x88, 0xba, 0xa6, 0x46, 0x6d, 0xb0, 0x79, 0x5e, 0x80, 0xba,
0x58, 0xdc, 0xa4, 0xbc, 0xe0, 0x8a, 0xea, 0x2b, 0xe5, 0x05, 0x57, 0x55, 0x47, 0xfb, 0x9f, 0xfc,
0xf0, 0xe0, 0xcc, 0xa6, 0x93, 0xd9, 0xe9, 0xee, 0xd0, 0x77, 0x1f, 0xf0, 0xdf, 0x84, 0x3c, 0xdb,
0x3b, 0xf3, 0x08, 0x7d, 0xe5, 0x07, 0xe7, 0x0f, 0x1c, 0x6f, 0xf4, 0x80, 0xe7, 0xac, 0x07, 0xb1,
0xae, 0xd3, 0x3c, 0xff, 0x91, 0xf9, 0xd3, 0xbf, 0x07, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x50, 0x5a,
0xbb, 0x94, 0x1e, 0x00, 0x00,
// 3003 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x59, 0x4b, 0x7b, 0xdb, 0xc6,
0xd5, 0x0e, 0x28, 0x8a, 0x22, 0x0f, 0x2f, 0x82, 0x46, 0xb2, 0xc4, 0x8f, 0xf2, 0x45, 0x41, 0x12,
0x9b, 0x9f, 0xbf, 0x44, 0x76, 0x94, 0xaf, 0x49, 0xda, 0x5c, 0x1a, 0x8a, 0x84, 0x2c, 0xd8, 0x14,
0xa9, 0x0c, 0x29, 0xc7, 0x8e, 0x17, 0x28, 0x44, 0x0e, 0x45, 0x44, 0xb8, 0xb0, 0xc0, 0xd0, 0xb6,
0xb2, 0x6a, 0xbb, 0xea, 0xd3, 0x1f, 0xd3, 0x5f, 0xd0, 0xe7, 0x69, 0xd7, 0xfd, 0x03, 0x5d, 0x76,
0xdb, 0x6d, 0x37, 0x5d, 0xf7, 0x99, 0x0b, 0x40, 0x80, 0xa2, 0x64, 0xf7, 0xb2, 0x91, 0x80, 0xf7,
0xbc, 0x73, 0xe6, 0xcc, 0xcc, 0x39, 0x67, 0x0e, 0x0e, 0x61, 0x33, 0xf0, 0xa7, 0x94, 0x04, 0xc1,
0x64, 0xf0, 0x40, 0x3c, 0xed, 0x4e, 0x02, 0x9f, 0xfa, 0xa8, 0x10, 0xe3, 0xb5, 0x42, 0x30, 0x19,
0x08, 0x54, 0xfb, 0xcb, 0x0a, 0xa0, 0x1e, 0xf1, 0x86, 0xc7, 0xd6, 0x85, 0x4b, 0x3c, 0x8a, 0xc9,
0x2f, 0xa7, 0x24, 0xa4, 0x08, 0x41, 0x76, 0x48, 0x42, 0x5a, 0x55, 0x76, 0x94, 0x7a, 0x09, 0xf3,
0x67, 0xa4, 0xc2, 0x92, 0xe5, 0xd2, 0x6a, 0x66, 0x47, 0xa9, 0x2f, 0x61, 0xf6, 0x88, 0xfe, 0x07,
0xf2, 0x96, 0x4b, 0x4d, 0x37, 0xb4, 0x68, 0xb5, 0xc4, 0xe1, 0x15, 0xcb, 0xa5, 0x47, 0xa1, 0x45,
0xd1, 0xbb, 0x50, 0x9a, 0x08, 0x95, 0xe6, 0xd8, 0x0a, 0xc7, 0xd5, 0x25, 0xae, 0xa8, 0x28, 0xb1,
0x43, 0x2b, 0x1c, 0xa3, 0x3a, 0xa8, 0x23, 0xdb, 0xb3, 0x1c, 0x73, 0xe0, 0xd0, 0x97, 0xe6, 0x90,
0x38, 0xd4, 0xaa, 0x66, 0x77, 0x94, 0xfa, 0x32, 0xae, 0x70, 0xbc, 0xe9, 0xd0, 0x97, 0x2d, 0x86,
0x26, 0x95, 0x59, 0xc3, 0x61, 0x50, 0xdd, 0x48, 0x29, 0x6b, 0x0c, 0x87, 0x01, 0xba, 0x07, 0xab,
0x11, 0x25, 0x10, 0x6b, 0xa8, 0x2e, 0xef, 0x28, 0xf5, 0x02, 0xae, 0x4c, 0xd2, 0x2b, 0xbb, 0x07,
0xab, 0xd4, 0x76, 0x89, 0x3f, 0xa5, 0x66, 0x48, 0x06, 0xbe, 0x37, 0x0c, 0xab, 0x39, 0x31, 0xa9,
0x84, 0x7b, 0x02, 0x45, 0x1a, 0x94, 0x47, 0x84, 0x98, 0x8e, 0xed, 0xda, 0xd4, 0x64, 0x2b, 0x5c,
0xe1, 0x2b, 0x2c, 0x8e, 0x08, 0x69, 0x33, 0xac, 0x67, 0x51, 0xf4, 0x3e, 0x54, 0x66, 0x1c, 0xbe,
0x0d, 0x65, 0x4e, 0x2a, 0x45, 0x24, 0xbe, 0x17, 0xbb, 0xa0, 0xfa, 0x53, 0x7a, 0xe6, 0xdb, 0xde,
0x99, 0x39, 0x18, 0x5b, 0x9e, 0x69, 0x0f, 0xab, 0xf9, 0x1d, 0xa5, 0x9e, 0xdd, 0xcf, 0x56, 0x95,
0x87, 0x0a, 0xae, 0x44, 0xd2, 0xe6, 0xd8, 0xf2, 0x8c, 0x21, 0xba, 0x0f, 0x6b, 0xf3, 0xfc, 0xb0,
0xba, 0xbe, 0xb3, 0x54, 0xcf, 0xe2, 0xd5, 0x34, 0x35, 0x44, 0x77, 0x61, 0xd5, 0xb1, 0x42, 0x6a,
0x8e, 0xfd, 0x89, 0x39, 0x99, 0x9e, 0x9e, 0x93, 0x8b, 0x6a, 0x85, 0xef, 0x4e, 0x99, 0xc1, 0x87,
0xfe, 0xe4, 0x98, 0x83, 0xe8, 0x16, 0x00, 0xdf, 0x66, 0x6e, 0x6a, 0xb5, 0xc0, 0x57, 0x5c, 0x60,
0x08, 0x37, 0x13, 0x7d, 0x0c, 0x45, 0xee, 0x1e, 0xe6, 0xd8, 0xf6, 0x68, 0x58, 0x85, 0x9d, 0xa5,
0x7a, 0x71, 0x4f, 0xdd, 0x75, 0x3c, 0xe6, 0x29, 0x98, 0x49, 0x0e, 0x6d, 0x8f, 0x62, 0x08, 0xa2,
0xc7, 0x10, 0x0d, 0x61, 0x9d, 0xb9, 0x85, 0x39, 0x98, 0x86, 0xd4, 0x77, 0xcd, 0x80, 0x0c, 0xfc,
0x60, 0x18, 0x56, 0x8b, 0x7c, 0xe8, 0xff, 0xef, 0xc6, 0xde, 0xb6, 0x7b, 0xd9, 0xbd, 0x76, 0x5b,
0x24, 0xa4, 0x4d, 0x3e, 0x0e, 0x8b, 0x61, 0xba, 0x47, 0x83, 0x0b, 0xbc, 0x36, 0x9c, 0xc7, 0xd1,
0x87, 0x80, 0x2c, 0xc7, 0xf1, 0x5f, 0x99, 0x21, 0x71, 0x46, 0xa6, 0x3c, 0xcb, 0xea, 0xea, 0x8e,
0x52, 0xcf, 0x63, 0x95, 0x4b, 0x7a, 0xc4, 0x19, 0x49, 0xf5, 0xe8, 0x53, 0x28, 0x73, 0x9b, 0x46,
0xc4, 0xa2, 0xd3, 0x80, 0x84, 0x55, 0x75, 0x67, 0xa9, 0x5e, 0xd9, 0x5b, 0x93, 0x0b, 0x39, 0x10,
0xf0, 0xbe, 0x4d, 0x71, 0x89, 0xf1, 0xe4, 0x7b, 0x88, 0xb6, 0xa1, 0xe0, 0x5a, 0xaf, 0xcd, 0x89,
0x15, 0xd0, 0xb0, 0xba, 0xb6, 0xa3, 0xd4, 0xcb, 0x38, 0xef, 0x5a, 0xaf, 0x8f, 0xd9, 0x3b, 0xda,
0x85, 0x75, 0xcf, 0x37, 0x6d, 0x6f, 0xe4, 0xd8, 0x67, 0x63, 0x6a, 0x4e, 0x27, 0x43, 0x8b, 0x92,
0xb0, 0x8a, 0xb8, 0x0d, 0x6b, 0x9e, 0x6f, 0x48, 0xc9, 0x89, 0x10, 0xa0, 0x8f, 0x60, 0x9d, 0x29,
0x0b, 0xc7, 0x56, 0x30, 0x34, 0x43, 0xfb, 0x47, 0x22, 0x3c, 0xe3, 0x06, 0x3b, 0x71, 0xac, 0xba,
0xd6, 0xeb, 0x1e, 0x93, 0xf4, 0xec, 0x1f, 0x09, 0xf7, 0x0e, 0x1e, 0x56, 0x93, 0xea, 0x26, 0x57,
0xc7, 0x1e, 0x6b, 0x2d, 0xd8, 0x5c, 0xbc, 0x41, 0x8c, 0xcb, 0x4e, 0x58, 0xe1, 0xaa, 0xd8, 0x23,
0xda, 0x80, 0xe5, 0x97, 0x96, 0x33, 0x25, 0x3c, 0x2c, 0x4b, 0x58, 0xbc, 0xfc, 0x2c, 0xf3, 0xb9,
0xa2, 0x8d, 0x61, 0xbd, 0x1f, 0x58, 0x83, 0xf3, 0xb9, 0xc8, 0x9e, 0x0f, 0x4c, 0xe5, 0x72, 0x60,
0x5e, 0xb1, 0xe0, 0xcc, 0x15, 0x0b, 0xd6, 0xbe, 0x86, 0x55, 0xee, 0x22, 0x07, 0x84, 0x5c, 0x97,
0x3f, 0xb6, 0x80, 0x65, 0x07, 0x1e, 0x4a, 0x22, 0x87, 0xe4, 0x2c, 0x97, 0x45, 0x91, 0x36, 0x04,
0x75, 0x36, 0x3e, 0x9c, 0xf8, 0x5e, 0x48, 0x58, 0x72, 0x60, 0x1e, 0xc4, 0x42, 0x80, 0x45, 0x18,
0xdf, 0x41, 0x85, 0x8f, 0xaa, 0x48, 0xfc, 0x80, 0x88, 0xfd, 0xbb, 0x2b, 0x02, 0xda, 0x74, 0xfc,
0xc1, 0x39, 0xcb, 0x22, 0xd6, 0x85, 0x54, 0x5f, 0x66, 0x70, 0xdb, 0x1f, 0x9c, 0xb7, 0x18, 0xa8,
0xbd, 0x10, 0x89, 0xae, 0xef, 0xf3, 0xb9, 0xfe, 0x85, 0xed, 0xd0, 0x60, 0x99, 0x3b, 0x33, 0x57,
0x5b, 0xdc, 0x2b, 0x25, 0xa3, 0x02, 0x0b, 0x91, 0xf6, 0x02, 0xd6, 0x53, 0xca, 0xe5, 0x2a, 0x6a,
0x90, 0x9f, 0x04, 0xc4, 0x76, 0xad, 0x33, 0x22, 0x35, 0xc7, 0xef, 0xa8, 0x0e, 0x2b, 0x23, 0xcb,
0x76, 0xa6, 0x41, 0xa4, 0xb8, 0x12, 0x79, 0xa9, 0x40, 0x71, 0x24, 0xd6, 0x6e, 0x42, 0x0d, 0x93,
0x90, 0xd0, 0x23, 0x3b, 0x0c, 0x6d, 0xdf, 0x6b, 0xfa, 0x1e, 0x0d, 0x7c, 0x47, 0xae, 0x40, 0xbb,
0x05, 0xdb, 0x0b, 0xa5, 0xc2, 0x04, 0x36, 0xf8, 0xdb, 0x29, 0x09, 0x2e, 0x16, 0x0f, 0xfe, 0x16,
0xb6, 0x17, 0x4a, 0xa5, 0xfd, 0x1f, 0xc2, 0xf2, 0xc4, 0xb2, 0x03, 0x76, 0xf6, 0x2c, 0xaa, 0x37,
0x13, 0x51, 0x7d, 0x6c, 0xd9, 0xc1, 0xa1, 0x1d, 0x52, 0x3f, 0xb8, 0xc0, 0x82, 0xf4, 0x38, 0x9b,
0x57, 0xd4, 0x8c, 0xd6, 0x86, 0x9b, 0xcf, 0x0c, 0x77, 0xe2, 0x07, 0x8b, 0xed, 0x9d, 0xe9, 0x54,
0xde, 0x42, 0xa7, 0x76, 0x07, 0x6e, 0x5d, 0xa1, 0x4d, 0xae, 0xef, 0x77, 0x0a, 0x14, 0x13, 0xe3,
0x58, 0x28, 0x7b, 0xfe, 0x90, 0x98, 0xa3, 0xc0, 0x77, 0xa3, 0x3d, 0x67, 0xc0, 0x41, 0xe0, 0xbb,
0xcc, 0x05, 0xb9, 0x90, 0xfa, 0x32, 0x5e, 0x72, 0xec, 0xb5, 0xef, 0xa3, 0x8f, 0x60, 0x65, 0x2c,
0x14, 0xf0, 0x34, 0x5f, 0xdc, 0x5b, 0x9f, 0x33, 0xab, 0x65, 0x51, 0x0b, 0x47, 0x9c, 0xc7, 0xd9,
0xfc, 0x92, 0x9a, 0x7d, 0x9c, 0xcd, 0x67, 0xd5, 0xe5, 0xc7, 0xd9, 0xfc, 0xb2, 0x9a, 0x7b, 0x9c,
0xcd, 0xe7, 0xd4, 0x15, 0xed, 0x6f, 0x0a, 0xe4, 0x23, 0x36, 0xb3, 0x84, 0x9d, 0xa0, 0xc9, 0xdc,
0x50, 0xfa, 0x6e, 0x9e, 0x01, 0x7d, 0xdb, 0x25, 0x68, 0x07, 0x4a, 0x5c, 0x98, 0x8e, 0x08, 0x60,
0x58, 0x83, 0x47, 0x05, 0xbf, 0x7f, 0x22, 0x06, 0x77, 0xff, 0xac, 0xbc, 0x7f, 0x04, 0x25, 0xba,
0x65, 0xc3, 0xe9, 0x60, 0x40, 0xc2, 0x50, 0xcc, 0xb2, 0x2c, 0x28, 0x12, 0xe3, 0x13, 0xdd, 0x85,
0xd5, 0x88, 0x12, 0xcd, 0x95, 0x13, 0xe1, 0x21, 0x61, 0x39, 0x5d, 0x1d, 0xd4, 0x24, 0xcf, 0x9d,
0xdd, 0x78, 0x95, 0x19, 0x91, 0x4d, 0x2a, 0x16, 0xaf, 0xed, 0xc0, 0xed, 0x47, 0xf3, 0x4e, 0xd7,
0xf4, 0xbd, 0x91, 0x7d, 0x16, 0xf9, 0xd6, 0xf7, 0x70, 0xe7, 0x4a, 0x86, 0xf4, 0xaf, 0xcf, 0x20,
0x37, 0xe0, 0x08, 0xdf, 0x9f, 0xe2, 0xde, 0x9d, 0xc4, 0xae, 0x2f, 0x1c, 0x28, 0xe9, 0xda, 0x73,
0xb8, 0xdd, 0xbb, 0x76, 0xf6, 0x7f, 0x5f, 0xf5, 0xbb, 0x70, 0xa7, 0x77, 0xbd, 0xd9, 0xda, 0xaf,
0x32, 0xb0, 0xb1, 0x88, 0xc0, 0x6e, 0xee, 0xb1, 0xe5, 0x8c, 0x4c, 0xc7, 0x1e, 0x91, 0xb8, 0xbc,
0x10, 0xd9, 0x7a, 0x95, 0x09, 0xda, 0xf6, 0x88, 0x44, 0xf5, 0xc5, 0x3d, 0x58, 0xe5, 0x97, 0x76,
0xe0, 0x9f, 0x5a, 0xa7, 0xb6, 0x63, 0x53, 0x91, 0xb7, 0x32, 0xb8, 0x32, 0xf6, 0x27, 0xc7, 0x33,
0x14, 0x6d, 0x42, 0xee, 0x15, 0x61, 0xf9, 0x96, 0x17, 0x51, 0x19, 0x2c, 0xdf, 0xd0, 0xa7, 0xb0,
0xe5, 0x5a, 0xaf, 0x6d, 0x77, 0xea, 0x9a, 0xb3, 0xd2, 0x27, 0x9c, 0x3a, 0x34, 0xe4, 0xae, 0x52,
0xc6, 0x37, 0xa4, 0x38, 0xbe, 0x01, 0xb8, 0x10, 0x35, 0xe1, 0xb6, 0x6b, 0x7b, 0x7c, 0x9c, 0xcc,
0x30, 0x66, 0x40, 0x1c, 0xeb, 0xb5, 0x69, 0x7b, 0x94, 0x04, 0x2f, 0x2d, 0x87, 0xbb, 0x51, 0x16,
0x6f, 0x4b, 0x56, 0x94, 0x8f, 0x18, 0xc7, 0x90, 0x14, 0xed, 0x07, 0xd8, 0xe2, 0x89, 0x23, 0x61,
0x68, 0xb4, 0xf3, 0xcc, 0xef, 0x03, 0xdf, 0x35, 0x59, 0x68, 0x45, 0x11, 0xc8, 0x80, 0x8e, 0x3f,
0x24, 0x2c, 0x02, 0xa9, 0x2f, 0x44, 0x32, 0x02, 0xa9, 0xcf, 0x05, 0xc9, 0x5a, 0x72, 0x29, 0x55,
0x4b, 0x6a, 0xe7, 0x50, 0xbd, 0x3c, 0x97, 0xf4, 0xa0, 0x1d, 0x28, 0x26, 0x77, 0x90, 0x4d, 0xa7,
0xe0, 0x24, 0x94, 0x0c, 0xed, 0xcc, 0x9b, 0x43, 0x5b, 0xfb, 0xb3, 0x02, 0x6b, 0xfb, 0x53, 0xdb,
0x19, 0xa6, 0xae, 0x89, 0xa4, 0x75, 0x4a, 0xba, 0xd2, 0x5d, 0x54, 0xc6, 0x66, 0x16, 0x96, 0xb1,
0x1f, 0x2e, 0xa8, 0x03, 0x97, 0x78, 0x1d, 0x98, 0x59, 0x50, 0x05, 0xde, 0x81, 0xe2, 0xac, 0xa8,
0x63, 0x47, 0xba, 0x54, 0x2f, 0x61, 0x18, 0x47, 0x15, 0x5d, 0x78, 0xa9, 0x2a, 0x5e, 0xbe, 0x54,
0x15, 0x6b, 0x9f, 0x03, 0x4a, 0xae, 0x45, 0xee, 0x59, 0x7c, 0xa1, 0x29, 0x57, 0x5f, 0x68, 0x37,
0xa1, 0xd6, 0x9b, 0x9e, 0x86, 0x83, 0xc0, 0x3e, 0x25, 0x87, 0xd4, 0x19, 0xe8, 0x2f, 0x89, 0x47,
0xc3, 0x28, 0xb4, 0xff, 0x91, 0x85, 0x42, 0x8c, 0xb2, 0x7a, 0xc1, 0xf6, 0x06, 0xbe, 0x1b, 0xad,
0xcb, 0x23, 0x0e, 0x5b, 0x9a, 0xf0, 0xfb, 0xb5, 0x48, 0xd4, 0x14, 0x12, 0x63, 0xc8, 0xf8, 0xa9,
0x7d, 0x90, 0xfc, 0x8c, 0xe0, 0x27, 0xb7, 0x41, 0xf0, 0xeb, 0xa0, 0xc6, 0xfa, 0xc7, 0xd4, 0x19,
0xc4, 0xfb, 0x86, 0x2b, 0x11, 0xce, 0x8c, 0x11, 0xcc, 0x58, 0x73, 0xc4, 0xcc, 0x0a, 0x66, 0x84,
0x4b, 0xe6, 0xbb, 0x50, 0x62, 0x19, 0x33, 0xa4, 0x96, 0x3b, 0x31, 0xbd, 0x50, 0xba, 0x7c, 0x31,
0xc6, 0x3a, 0x21, 0xfa, 0x0a, 0x80, 0xb0, 0xf5, 0x99, 0xf4, 0x62, 0x42, 0x78, 0xd2, 0xac, 0xec,
0xdd, 0x4e, 0xf8, 0x4e, 0xbc, 0x01, 0xbb, 0xfc, 0x6f, 0xff, 0x62, 0x42, 0x70, 0x81, 0x44, 0x8f,
0xe8, 0x6b, 0x28, 0x8f, 0xfc, 0xe0, 0x15, 0x2b, 0x02, 0x39, 0x28, 0x2f, 0x96, 0xad, 0x84, 0x86,
0x03, 0x21, 0xe7, 0xc3, 0x0f, 0xdf, 0xc1, 0xa5, 0x51, 0xe2, 0x1d, 0x3d, 0x01, 0x14, 0x8d, 0xe7,
0xf7, 0x80, 0x50, 0x92, 0xe7, 0x4a, 0xb6, 0x2f, 0x2b, 0x61, 0x51, 0x1a, 0x29, 0x52, 0x47, 0x73,
0x18, 0xfa, 0x02, 0x4a, 0x21, 0xa1, 0xd4, 0x21, 0x52, 0x4d, 0x81, 0xab, 0xd9, 0x4c, 0x55, 0xe9,
0x4c, 0x1c, 0x69, 0x28, 0x86, 0xb3, 0x57, 0xb4, 0x0f, 0xab, 0x8e, 0xed, 0x9d, 0x27, 0xcd, 0x00,
0x3e, 0xbe, 0x9a, 0x18, 0xdf, 0xb6, 0xbd, 0xf3, 0xa4, 0x0d, 0x65, 0x27, 0x09, 0x68, 0x5f, 0x42,
0x21, 0xde, 0x25, 0x54, 0x84, 0x95, 0x93, 0xce, 0x93, 0x4e, 0xf7, 0xbb, 0x8e, 0xfa, 0x0e, 0xca,
0x43, 0xb6, 0xa7, 0x77, 0x5a, 0xaa, 0xc2, 0x60, 0xac, 0x37, 0x75, 0xe3, 0xa9, 0xae, 0x66, 0xd8,
0xcb, 0x41, 0x17, 0x7f, 0xd7, 0xc0, 0x2d, 0x75, 0x69, 0x7f, 0x05, 0x96, 0xf9, 0xbc, 0xda, 0x1f,
0x14, 0xc8, 0xf3, 0x13, 0xf4, 0x46, 0x3e, 0xfa, 0x3f, 0x88, 0x9d, 0x8b, 0x5f, 0x7f, 0xac, 0x02,
0xe4, 0x5e, 0x57, 0xc6, 0xb1, 0xc3, 0xf4, 0x25, 0xce, 0xc8, 0xb1, 0x6b, 0xc4, 0xe4, 0x8c, 0x20,
0x47, 0x82, 0x98, 0x7c, 0x3f, 0xa1, 0x39, 0x95, 0x95, 0xb2, 0x78, 0x35, 0x12, 0x44, 0x77, 0x70,
0xf2, 0x6b, 0x2d, 0x75, 0x57, 0x27, 0xbe, 0xd6, 0x24, 0x57, 0xfb, 0x0c, 0x4a, 0xc9, 0x33, 0x47,
0xf7, 0x20, 0x6b, 0x7b, 0x23, 0x5f, 0x06, 0xe2, 0xfa, 0x9c, 0x73, 0xb1, 0x45, 0x62, 0x4e, 0xd0,
0x10, 0xa8, 0xf3, 0xe7, 0xac, 0x95, 0xa1, 0x98, 0x38, 0x34, 0xed, 0xaf, 0x0a, 0x94, 0x53, 0x87,
0xf0, 0xd6, 0xda, 0xd1, 0x57, 0x50, 0x7a, 0x65, 0x07, 0xc4, 0x4c, 0xd6, 0xa3, 0x95, 0xbd, 0x5a,
0xba, 0x1e, 0x8d, 0xfe, 0x37, 0xfd, 0x21, 0xc1, 0x45, 0xc6, 0x97, 0x00, 0xfa, 0x39, 0x54, 0xa2,
0x8b, 0x64, 0x48, 0xa8, 0x65, 0x3b, 0x7c, 0xab, 0x2a, 0x29, 0xf7, 0x90, 0xdc, 0x16, 0x97, 0xe3,
0xf2, 0x28, 0xf9, 0x8a, 0x3e, 0x98, 0x29, 0x08, 0x69, 0x60, 0x7b, 0x67, 0x7c, 0xff, 0x0a, 0x31,
0xad, 0xc7, 0x41, 0x56, 0xea, 0x95, 0xe5, 0x5d, 0xd6, 0xa3, 0x16, 0x9d, 0xb2, 0x4f, 0xad, 0xe5,
0x90, 0x5a, 0x32, 0x93, 0x55, 0x52, 0xb1, 0x95, 0x20, 0x12, 0x2c, 0x58, 0xa9, 0x72, 0x3c, 0x73,
0xa9, 0x1c, 0x5f, 0x66, 0x19, 0x43, 0x24, 0xda, 0xe2, 0x1e, 0x92, 0x8b, 0x3f, 0xec, 0xb7, 0x9b,
0x0d, 0x4a, 0x89, 0x3b, 0xa1, 0x58, 0x10, 0x64, 0xfd, 0xf3, 0x35, 0x40, 0xd3, 0x0e, 0x06, 0x53,
0x9b, 0x3e, 0x21, 0x17, 0xec, 0x5a, 0x8b, 0x32, 0xba, 0x48, 0x7b, 0xb9, 0x81, 0xc8, 0xe2, 0x5b,
0xb0, 0x12, 0x25, 0x22, 0x91, 0xdf, 0x72, 0x63, 0x9e, 0x80, 0xb4, 0x3f, 0x66, 0x61, 0x5b, 0x1e,
0xa9, 0x38, 0x0d, 0x4a, 0x82, 0x01, 0x99, 0xc4, 0xdf, 0x69, 0x8f, 0x60, 0x63, 0x96, 0x54, 0xc5,
0x44, 0x66, 0xf4, 0xed, 0x57, 0xdc, 0xbb, 0x91, 0x58, 0xe9, 0xcc, 0x0c, 0x8c, 0xe2, 0x64, 0x3b,
0x33, 0xed, 0x61, 0x42, 0x91, 0xe5, 0xfa, 0x53, 0x4f, 0xba, 0xa8, 0xc8, 0x78, 0x68, 0xe6, 0xce,
0x4c, 0xc4, 0x3d, 0xfa, 0x1e, 0xc4, 0x4e, 0x6e, 0x92, 0xd7, 0x13, 0x3b, 0xb8, 0xe0, 0xd9, 0xaf,
0x3c, 0x4b, 0xb7, 0x3a, 0x47, 0x2f, 0x7d, 0x3c, 0x65, 0x2e, 0x7f, 0x3c, 0x7d, 0x01, 0xb5, 0x38,
0x3a, 0x64, 0x63, 0x86, 0x0c, 0xe3, 0xdb, 0x6f, 0x85, 0xdb, 0xb0, 0x15, 0x31, 0x70, 0x44, 0x90,
0x57, 0xe0, 0x43, 0xd8, 0x48, 0x84, 0xd6, 0xcc, 0x74, 0x11, 0x89, 0x68, 0x16, 0x5d, 0x49, 0xd3,
0xe3, 0x11, 0xd2, 0x74, 0x51, 0x0b, 0xc5, 0xf9, 0x5f, 0x9a, 0xfe, 0x0b, 0xa8, 0xcc, 0x35, 0x2e,
0xf2, 0xfc, 0xdc, 0x7f, 0x7a, 0x39, 0xb3, 0x2e, 0x3a, 0x9e, 0xdd, 0x05, 0xdd, 0x8b, 0xf2, 0x20,
0xd5, 0xb9, 0xb8, 0x05, 0xe0, 0x7b, 0xb6, 0xef, 0x99, 0xa7, 0x8e, 0x7f, 0xca, 0x13, 0x6e, 0x09,
0x17, 0x38, 0xb2, 0xef, 0xf8, 0xa7, 0xb5, 0x6f, 0x00, 0xfd, 0x87, 0x1f, 0xf8, 0x7f, 0x52, 0xe0,
0xe6, 0x62, 0x13, 0xe5, 0x3d, 0xff, 0x5f, 0x73, 0xa1, 0x2f, 0x20, 0x67, 0x0d, 0xa8, 0xed, 0x7b,
0x32, 0x33, 0xbc, 0x97, 0x18, 0x8a, 0x49, 0xe8, 0x3b, 0x2f, 0xc9, 0xa1, 0xef, 0x0c, 0xa5, 0x31,
0x0d, 0x4e, 0xc5, 0x72, 0x48, 0x2a, 0xe8, 0x96, 0xd2, 0x41, 0xa7, 0xfd, 0x46, 0x81, 0x2d, 0xd1,
0x45, 0x60, 0x27, 0x2e, 0x82, 0x3a, 0x0a, 0x80, 0x3d, 0x00, 0xee, 0x26, 0x13, 0xdf, 0xf6, 0x68,
0x9c, 0xc3, 0x44, 0x54, 0xca, 0xda, 0xe0, 0x98, 0x89, 0x70, 0x81, 0xd1, 0xf8, 0x23, 0xfa, 0x64,
0xce, 0xd0, 0xe4, 0x3d, 0x39, 0x9b, 0x21, 0x6d, 0xa0, 0x56, 0x83, 0xea, 0x65, 0x1b, 0xc4, 0x16,
0xde, 0xff, 0x75, 0x16, 0xca, 0xa9, 0xd4, 0x95, 0xbe, 0xbb, 0xca, 0x50, 0xe8, 0x74, 0xcd, 0x96,
0xde, 0x6f, 0x18, 0x6d, 0x55, 0x41, 0x2a, 0x94, 0xba, 0x1d, 0xa3, 0xdb, 0x31, 0x5b, 0x7a, 0xb3,
0xdb, 0x62, 0xb7, 0xd8, 0x0d, 0x58, 0x6b, 0x1b, 0x9d, 0x27, 0x66, 0xa7, 0xdb, 0x37, 0xf5, 0xb6,
0xf1, 0xc8, 0xd8, 0x6f, 0xeb, 0xea, 0x12, 0xda, 0x00, 0xb5, 0xdb, 0x31, 0x9b, 0x87, 0x0d, 0xa3,
0x63, 0xf6, 0x8d, 0x23, 0xbd, 0x7b, 0xd2, 0x57, 0xb3, 0x0c, 0x65, 0xe9, 0xc6, 0xd4, 0x9f, 0x35,
0x75, 0xbd, 0xd5, 0x33, 0x8f, 0x1a, 0xcf, 0xd4, 0x65, 0x54, 0x85, 0x0d, 0xa3, 0xd3, 0x3b, 0x39,
0x38, 0x30, 0x9a, 0x86, 0xde, 0xe9, 0x9b, 0xfb, 0x8d, 0x76, 0xa3, 0xd3, 0xd4, 0xd5, 0x1c, 0xda,
0x04, 0x64, 0x74, 0x9a, 0xdd, 0xa3, 0xe3, 0xb6, 0xde, 0xd7, 0xcd, 0xe8, 0xb6, 0x5c, 0x41, 0xeb,
0xb0, 0xca, 0xf5, 0x34, 0x5a, 0x2d, 0xf3, 0xa0, 0x61, 0xb4, 0xf5, 0x96, 0x9a, 0x67, 0x96, 0x48,
0x46, 0xcf, 0x6c, 0x19, 0xbd, 0xc6, 0x3e, 0x83, 0x0b, 0x6c, 0x4e, 0xa3, 0xf3, 0xb4, 0x6b, 0x34,
0x75, 0xb3, 0xc9, 0xd4, 0x32, 0x14, 0x18, 0x39, 0x42, 0x4f, 0x3a, 0x2d, 0x1d, 0x1f, 0x37, 0x8c,
0x96, 0x5a, 0x44, 0xdb, 0xb0, 0x15, 0xc1, 0xfa, 0xb3, 0x63, 0x03, 0x3f, 0x37, 0xfb, 0xdd, 0xae,
0xd9, 0xeb, 0x76, 0x3b, 0x6a, 0x29, 0xa9, 0x89, 0xad, 0xb6, 0x7b, 0xac, 0x77, 0xd4, 0x32, 0xda,
0x82, 0xf5, 0xa3, 0xe3, 0x63, 0x33, 0x92, 0x44, 0x8b, 0xad, 0x30, 0x7a, 0xa3, 0xd5, 0xc2, 0x7a,
0xaf, 0x67, 0x1e, 0x19, 0xbd, 0xa3, 0x46, 0xbf, 0x79, 0xa8, 0xae, 0xb2, 0x25, 0xf5, 0xf4, 0xbe,
0xd9, 0xef, 0xf6, 0x1b, 0xed, 0x19, 0xae, 0x32, 0x83, 0x66, 0x38, 0x9b, 0xb4, 0xdd, 0xfd, 0x4e,
0x5d, 0x63, 0x1b, 0xce, 0xe0, 0xee, 0x53, 0x69, 0x22, 0x62, 0x6b, 0x97, 0xc7, 0x13, 0xcd, 0xa9,
0xae, 0x33, 0xd0, 0xe8, 0x3c, 0x6d, 0xb4, 0x8d, 0x96, 0xf9, 0x44, 0x7f, 0xce, 0xab, 0x8d, 0x0d,
0x06, 0x0a, 0xcb, 0xcc, 0x63, 0xdc, 0x7d, 0xc4, 0x0c, 0x51, 0x6f, 0x20, 0x04, 0x95, 0xa6, 0x81,
0x9b, 0x27, 0xed, 0x06, 0x36, 0x71, 0xf7, 0xa4, 0xaf, 0xab, 0x9b, 0xf7, 0x7f, 0xaf, 0x40, 0x29,
0x79, 0x9b, 0xb0, 0x53, 0x37, 0x3a, 0xe6, 0x41, 0xdb, 0x78, 0x74, 0xd8, 0x17, 0x4e, 0xd0, 0x3b,
0x69, 0xb2, 0x23, 0xd3, 0x59, 0x15, 0x83, 0xa0, 0x22, 0x36, 0x3d, 0x5e, 0x6c, 0x86, 0xcd, 0x25,
0xb1, 0x4e, 0x57, 0xea, 0x5d, 0x62, 0xc6, 0x4b, 0x50, 0xc7, 0xb8, 0x8b, 0xd5, 0x2c, 0x7a, 0x1f,
0x76, 0x24, 0xc2, 0xce, 0x15, 0x63, 0xbd, 0xd9, 0x37, 0x8f, 0x1b, 0xcf, 0x8f, 0xd8, 0xb1, 0x0b,
0x27, 0xeb, 0xa9, 0xcb, 0xe8, 0x0e, 0x6c, 0xc7, 0xac, 0x45, 0x7e, 0x71, 0xff, 0x4b, 0xa8, 0x5e,
0x15, 0x95, 0x08, 0x20, 0xd7, 0xd3, 0xfb, 0xfd, 0xb6, 0x2e, 0x2a, 0xaf, 0x03, 0xe1, 0xb8, 0x00,
0x39, 0xac, 0xf7, 0x4e, 0x8e, 0x74, 0x35, 0x73, 0xff, 0x27, 0xa0, 0xce, 0x87, 0x0a, 0x93, 0xeb,
0x1d, 0xe6, 0x32, 0xea, 0x3b, 0x2c, 0x00, 0xa4, 0xff, 0xa8, 0x0a, 0x53, 0xd1, 0x38, 0xe9, 0x77,
0xd5, 0xcc, 0xde, 0xdf, 0x8b, 0x90, 0xe3, 0x5f, 0x10, 0x01, 0xfa, 0x06, 0xca, 0x89, 0x9e, 0xef,
0xd3, 0x3d, 0x74, 0xeb, 0xda, 0x6e, 0x70, 0x2d, 0x6a, 0x7c, 0x49, 0xf8, 0xa1, 0x82, 0xf6, 0xa1,
0x92, 0xec, 0x5d, 0x3e, 0xdd, 0x43, 0xc9, 0xc2, 0x7b, 0x41, 0x5b, 0x73, 0x81, 0x8e, 0x27, 0xa0,
0xea, 0x21, 0xb5, 0x5d, 0x76, 0xff, 0xcb, 0xee, 0x22, 0xaa, 0x25, 0x13, 0x57, 0xba, 0x65, 0x59,
0xdb, 0x5e, 0x28, 0x93, 0xa9, 0xf4, 0x5b, 0x56, 0x6b, 0xc5, 0xfd, 0xbd, 0x4b, 0x0b, 0x4a, 0x37,
0x15, 0x6b, 0xb7, 0xaf, 0x12, 0xcb, 0xfe, 0xc1, 0xd2, 0x6f, 0x33, 0x6c, 0x8d, 0xe5, 0x84, 0x6c,
0xc1, 0x2e, 0xcd, 0x29, 0x5d, 0x50, 0x91, 0xa0, 0x21, 0xac, 0x2f, 0xe8, 0xfd, 0xa1, 0x0f, 0xd2,
0xf9, 0xf9, 0x8a, 0xce, 0x61, 0xed, 0xee, 0x9b, 0x68, 0x72, 0xf1, 0x43, 0x58, 0x5f, 0xd0, 0x24,
0x4c, 0xcd, 0x72, 0x75, 0x8b, 0x31, 0x35, 0xcb, 0x75, 0xbd, 0xc6, 0x1f, 0xe0, 0xc6, 0xc2, 0x4e,
0x1f, 0xba, 0x97, 0x50, 0x70, 0x5d, 0x67, 0xb1, 0x56, 0x7f, 0x33, 0x51, 0xce, 0x35, 0x81, 0xad,
0x2b, 0x5a, 0x53, 0xe8, 0x7f, 0x13, 0x4a, 0xae, 0x6f, 0x70, 0xd5, 0xee, 0xbf, 0x0d, 0x75, 0x36,
0x63, 0xef, 0x2d, 0x66, 0xec, 0xbd, 0xfd, 0x8c, 0x6f, 0x68, 0x52, 0xa1, 0x17, 0xa0, 0xce, 0x77,
0x4d, 0x90, 0x36, 0x7f, 0x16, 0x97, 0xdb, 0x37, 0xb5, 0xf7, 0xae, 0xe5, 0x48, 0xe5, 0x06, 0xc0,
0xac, 0xb1, 0x80, 0x6e, 0x26, 0x86, 0x5c, 0xea, 0x9d, 0xd4, 0x6e, 0x5d, 0x21, 0x95, 0xaa, 0xfa,
0xb0, 0xbe, 0xa0, 0xd3, 0x90, 0xf2, 0xae, 0xab, 0x3b, 0x11, 0xb5, 0x8d, 0x45, 0x1f, 0xe4, 0x0f,
0x15, 0x74, 0x24, 0x02, 0x36, 0xfa, 0x61, 0xe8, 0x0d, 0x19, 0xa8, 0xba, 0xf8, 0xc3, 0x61, 0x1a,
0xf2, 0x50, 0x7d, 0xa8, 0xa0, 0x2e, 0x94, 0x92, 0x59, 0xe7, 0x8d, 0xe9, 0xe8, 0x8d, 0x0a, 0x47,
0xb0, 0x9a, 0x2a, 0xda, 0xfc, 0x20, 0xe5, 0xe7, 0xd7, 0xd5, 0x75, 0xa9, 0x88, 0xba, 0xa6, 0x46,
0xad, 0xb3, 0x79, 0x5e, 0x80, 0x3a, 0x5f, 0xdc, 0xa4, 0xbc, 0xe0, 0x8a, 0xea, 0x2b, 0xe5, 0x05,
0x57, 0x55, 0x47, 0xfb, 0x1f, 0x7f, 0xff, 0xe0, 0xcc, 0xa6, 0xe3, 0xe9, 0xe9, 0xee, 0xc0, 0x77,
0x1f, 0xf0, 0xdf, 0x84, 0x3c, 0xdb, 0x3b, 0xf3, 0x08, 0x7d, 0xe5, 0x07, 0xe7, 0x0f, 0x1c, 0x6f,
0xf8, 0x80, 0xe7, 0xac, 0x07, 0xb1, 0xae, 0xd3, 0x1c, 0xff, 0xd9, 0xf9, 0x93, 0x7f, 0x06, 0x00,
0x00, 0xff, 0xff, 0x59, 0xf4, 0x3e, 0x26, 0xa6, 0x1e, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

5
lnrpc/routerrpc/router.proto

@ -279,6 +279,11 @@ message SendPaymentRequest {
value is in milli-satoshis.
*/
uint64 max_shard_size_msat = 21;
/*
If set, an AMP-payment will be attempted.
*/
bool amp = 22;
}
message TrackPaymentRequest {

9
lnrpc/routerrpc/router.swagger.json

@ -610,7 +610,9 @@
"ANCHORS_REQ",
"ANCHORS_OPT",
"ANCHORS_ZERO_FEE_HTLC_REQ",
"ANCHORS_ZERO_FEE_HTLC_OPT"
"ANCHORS_ZERO_FEE_HTLC_OPT",
"AMP_REQ",
"AMP_OPT"
],
"default": "DATALOSS_PROTECT_REQ"
},
@ -1493,6 +1495,11 @@
"type": "string",
"format": "uint64",
"description": "The largest payment split that should be attempted when making a payment if\nsplitting is necessary. Setting this value will effectively cause lnd to\nsplit more aggressively, vs only when it thinks it needs to. Note that this\nvalue is in milli-satoshis."
},
"amp": {
"type": "boolean",
"format": "boolean",
"description": "If set, an AMP-payment will be attempted."
}
}
},

103
lnrpc/routerrpc/router_backend.go

@ -2,6 +2,7 @@ package routerrpc
import (
"context"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
@ -13,6 +14,7 @@ import (
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/feature"
"github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
@ -698,7 +700,11 @@ func (r *RouterBackend) extractIntentFromSendRequest(
payIntent.MaxParts = 1
}
copy(payIntent.PaymentHash[:], payReq.PaymentHash[:])
err = payIntent.SetPaymentHash(*payReq.PaymentHash)
if err != nil {
return nil, err
}
destKey := payReq.Destination.SerializeCompressed()
copy(payIntent.Target[:], destKey)
@ -736,22 +742,96 @@ func (r *RouterBackend) extractIntentFromSendRequest(
payIntent.Amount = reqAmt
// Payment hash.
copy(payIntent.PaymentHash[:], rpcPayReq.PaymentHash)
// Parse destination feature bits.
features, err := UnmarshalFeatures(rpcPayReq.DestFeatures)
if err != nil {
return nil, err
}
// If the payment addresses is specified, then we'll also
// populate that now as well.
if len(rpcPayReq.PaymentAddr) != 0 {
var payAddr [32]byte
copy(payAddr[:], rpcPayReq.PaymentAddr)
// Validate the features if any was specified.
if features != nil {
err = feature.ValidateDeps(features)
if err != nil {
return nil, err
}
}
// If this is an AMP payment, we must generate the initial
// randomness.
if rpcPayReq.Amp {
// If no destination features were specified, we set
// those necessary for AMP payments.
if features == nil {
ampFeatures := []lnrpc.FeatureBit{
lnrpc.FeatureBit_TLV_ONION_OPT,
lnrpc.FeatureBit_PAYMENT_ADDR_OPT,
lnrpc.FeatureBit_MPP_OPT,
lnrpc.FeatureBit_AMP_OPT,
}
features, err = UnmarshalFeatures(ampFeatures)
if err != nil {
return nil, err
}
}
// First make sure the destination supports AMP.
if !features.HasFeature(lnwire.AMPOptional) {
return nil, fmt.Errorf("destination doesn't " +
"support AMP payments")
}
// If no payment address is set, generate a random one.
var payAddr [32]byte
if len(rpcPayReq.PaymentAddr) == 0 {
_, err = rand.Read(payAddr[:])
if err != nil {
return nil, err
}
} else {
copy(payAddr[:], rpcPayReq.PaymentAddr)
}
payIntent.PaymentAddr = &payAddr
// Generate random SetID and root share.
var setID [32]byte
_, err = rand.Read(setID[:])
if err != nil {
return nil, err
}
var rootShare [32]byte
_, err = rand.Read(rootShare[:])
if err != nil {
return nil, err
}
err := payIntent.SetAMP(&routing.AMPOptions{
SetID: setID,
RootShare: rootShare,
})
if err != nil {
return nil, err
}
} else {
// Payment hash.
paymentHash, err := lntypes.MakeHash(rpcPayReq.PaymentHash)
if err != nil {
return nil, err
}
err = payIntent.SetPaymentHash(paymentHash)
if err != nil {
return nil, err
}
// If the payment addresses is specified, then we'll
// also populate that now as well.
if len(rpcPayReq.PaymentAddr) != 0 {
var payAddr [32]byte
copy(payAddr[:], rpcPayReq.PaymentAddr)
payIntent.PaymentAddr = &payAddr
}
}
payIntent.DestFeatures = features
@ -1217,7 +1297,7 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) (
htlcs = append(htlcs, htlc)
}
paymentHash := payment.Info.PaymentHash
paymentID := payment.Info.PaymentIdentifier
creationTimeNS := MarshalTimeNano(payment.Info.CreationTime)
failureReason, err := marshallPaymentFailureReason(
@ -1228,7 +1308,8 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) (
}
return &lnrpc.Payment{
PaymentHash: hex.EncodeToString(paymentHash[:]),
// TODO: set this to setID for AMP-payments?
PaymentHash: hex.EncodeToString(paymentID[:]),
Value: satValue,
ValueMsat: msatValue,
ValueSat: satValue,

16
lnrpc/routerrpc/router_server.go

@ -316,21 +316,21 @@ func (s *Server) SendPaymentV2(req *SendPaymentRequest,
if err == channeldb.ErrPaymentInFlight ||
err == channeldb.ErrAlreadyPaid {
log.Debugf("SendPayment async result for hash %x: %v",
payment.PaymentHash, err)
log.Debugf("SendPayment async result for payment %x: %v",
payment.Identifier(), err)
return status.Error(
codes.AlreadyExists, err.Error(),
)
}
log.Errorf("SendPayment async error for hash %x: %v",
payment.PaymentHash, err)
log.Errorf("SendPayment async error for payment %x: %v",
payment.Identifier(), err)
return err
}
return s.trackPayment(payment.PaymentHash, stream, req.NoInflightUpdates)
return s.trackPayment(payment.Identifier(), stream, req.NoInflightUpdates)
}
// EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it
@ -719,14 +719,14 @@ func (s *Server) TrackPaymentV2(request *TrackPaymentRequest,
}
// trackPayment writes payment status updates to the provided stream.
func (s *Server) trackPayment(paymentHash lntypes.Hash,
func (s *Server) trackPayment(identifier lntypes.Hash,
stream Router_TrackPaymentV2Server, noInflightUpdates bool) error {
router := s.cfg.RouterBackend
// Subscribe to the outcome of this payment.
subscription, err := router.Tower.SubscribePayment(
paymentHash,
identifier,
)
switch {
case err == channeldb.ErrPaymentNotInitiated:
@ -769,7 +769,7 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash,
return errServerShuttingDown
case <-stream.Context().Done():
log.Debugf("Payment status stream %v canceled", paymentHash)
log.Debugf("Payment status stream %v canceled", identifier)
return stream.Context().Err()
}
}

1601
lnrpc/rpc.pb.go

@ -360,6 +360,8 @@ const (
FeatureBit_ANCHORS_OPT FeatureBit = 21
FeatureBit_ANCHORS_ZERO_FEE_HTLC_REQ FeatureBit = 22
FeatureBit_ANCHORS_ZERO_FEE_HTLC_OPT FeatureBit = 23
FeatureBit_AMP_REQ FeatureBit = 30
FeatureBit_AMP_OPT FeatureBit = 31
)
var FeatureBit_name = map[int32]string{
@ -386,6 +388,8 @@ var FeatureBit_name = map[int32]string{
21: "ANCHORS_OPT",
22: "ANCHORS_ZERO_FEE_HTLC_REQ",
23: "ANCHORS_ZERO_FEE_HTLC_OPT",
30: "AMP_REQ",
31: "AMP_OPT",
}
var FeatureBit_value = map[string]int32{
@ -412,6 +416,8 @@ var FeatureBit_value = map[string]int32{
"ANCHORS_OPT": 21,
"ANCHORS_ZERO_FEE_HTLC_REQ": 22,
"ANCHORS_ZERO_FEE_HTLC_OPT": 23,
"AMP_REQ": 30,
"AMP_OPT": 31,
}
func (x FeatureBit) String() string {
@ -13235,803 +13241,804 @@ func init() {
func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) }
var fileDescriptor_77a6da22d6a3feb1 = []byte{
// 12733 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5b, 0x6c, 0x23, 0x59,
0x7a, 0x18, 0xdc, 0xbc, 0x89, 0xe4, 0x47, 0x52, 0xa2, 0x8e, 0x6e, 0x6c, 0xf5, 0xf4, 0x74, 0x4f,
0xcd, 0xec, 0x4c, 0x6f, 0xcf, 0x8c, 0xa6, 0xa7, 0x67, 0x7a, 0x2e, 0x3b, 0xbf, 0xd7, 0x4b, 0x49,
0x54, 0x8b, 0xdb, 0x12, 0xa9, 0x2d, 0x52, 0x33, 0x6e, 0xc3, 0x76, 0xb9, 0x44, 0x1e, 0x49, 0xf5,
0x37, 0x59, 0xc5, 0xad, 0x2a, 0xaa, 0xa5, 0x0d, 0x02, 0xf8, 0xc1, 0xb1, 0x03, 0xc3, 0x09, 0x60,
0x20, 0x0e, 0x10, 0x24, 0x46, 0x12, 0x24, 0x48, 0xde, 0x0c, 0x03, 0xb6, 0x9f, 0x92, 0x87, 0x3c,
0x05, 0x08, 0x90, 0x20, 0x08, 0x10, 0x23, 0x97, 0x87, 0x04, 0x01, 0x12, 0x07, 0x88, 0x81, 0xd8,
0x80, 0x1f, 0x93, 0x20, 0xc1, 0xf9, 0xce, 0xa5, 0x4e, 0x5d, 0xd4, 0xdd, 0xb3, 0x9e, 0xdd, 0x17,
0x89, 0xf5, 0x9d, 0xef, 0xdc, 0xcf, 0xf9, 0xce, 0x77, 0x3b, 0xdf, 0x81, 0xaa, 0x3f, 0x1b, 0x6d,
0xcd, 0x7c, 0x2f, 0xf4, 0x48, 0x69, 0xe2, 0xfa, 0xb3, 0x91, 0xf1, 0xc7, 0x39, 0x28, 0x1e, 0x87,
0x97, 0x1e, 0x79, 0x04, 0x75, 0x7b, 0x3c, 0xf6, 0x69, 0x10, 0x58, 0xe1, 0xd5, 0x8c, 0xb6, 0x72,
0x77, 0x73, 0xf7, 0x16, 0x1f, 0x92, 0x2d, 0x44, 0xdb, 0x6a, 0xf3, 0xa4, 0xe1, 0xd5, 0x8c, 0x9a,
0x35, 0x3b, 0xfa, 0x20, 0x2d, 0x28, 0x8b, 0xcf, 0x56, 0xfe, 0x6e, 0xee, 0x5e, 0xd5, 0x94, 0x9f,
0xe4, 0x36, 0x80, 0x3d, 0xf5, 0xe6, 0x6e, 0x68, 0x05, 0x76, 0xd8, 0x2a, 0xdc, 0xcd, 0xdd, 0x2b,
0x98, 0x55, 0x0e, 0x19, 0xd8, 0x21, 0xb9, 0x05, 0xd5, 0xd9, 0x33, 0x2b, 0x18, 0xf9, 0xce, 0x2c,
0x6c, 0x15, 0x31, 0x6b, 0x65, 0xf6, 0x6c, 0x80, 0xdf, 0xe4, 0x5d, 0xa8, 0x78, 0xf3, 0x70, 0xe6,
0x39, 0x6e, 0xd8, 0x2a, 0xdd, 0xcd, 0xdd, 0xab, 0x3d, 0x5c, 0x12, 0x0d, 0xe9, 0xcf, 0xc3, 0x23,
0x06, 0x36, 0x15, 0x02, 0x79, 0x0b, 0x1a, 0x23, 0xcf, 0x3d, 0x75, 0xfc, 0xa9, 0x1d, 0x3a, 0x9e,
0x1b, 0xb4, 0x16, 0xb0, 0xae, 0x38, 0xd0, 0xf8, 0xe7, 0x79, 0xa8, 0x0d, 0x7d, 0xdb, 0x0d, 0xec,
0x11, 0x03, 0x90, 0x0d, 0x28, 0x87, 0x97, 0xd6, 0xb9, 0x1d, 0x9c, 0x63, 0x57, 0xab, 0xe6, 0x42,
0x78, 0xb9, 0x6f, 0x07, 0xe7, 0x64, 0x1d, 0x16, 0x78, 0x2b, 0xb1, 0x43, 0x05, 0x53, 0x7c, 0x91,
0x77, 0x61, 0xd9, 0x9d, 0x4f, 0xad, 0x78, 0x55, 0xac, 0x5b, 0x25, 0xb3, 0xe9, 0xce, 0xa7, 0x3b,
0x3a, 0x9c, 0x75, 0xfe, 0x64, 0xe2, 0x8d, 0x9e, 0xf1, 0x0a, 0x78, 0xf7, 0xaa, 0x08, 0xc1, 0x3a,
0xde, 0x80, 0xba, 0x48, 0xa6, 0xce, 0xd9, 0x39, 0xef, 0x63, 0xc9, 0xac, 0x71, 0x04, 0x04, 0xb1,
0x12, 0x42, 0x67, 0x4a, 0xad, 0x20, 0xb4, 0xa7, 0x33, 0xd1, 0xa5, 0x2a, 0x83, 0x0c, 0x18, 0x00,
0x93, 0xbd, 0xd0, 0x9e, 0x58, 0xa7, 0x94, 0x06, 0xad, 0xb2, 0x48, 0x66, 0x90, 0x3d, 0x4a, 0x03,
0xf2, 0x2d, 0x58, 0x1c, 0xd3, 0x20, 0xb4, 0xc4, 0x64, 0xd0, 0xa0, 0x55, 0xb9, 0x5b, 0xb8, 0x57,
0x35, 0x1b, 0x0c, 0xda, 0x96, 0x40, 0xf2, 0x1a, 0x80, 0x6f, 0x3f, 0xb7, 0xd8, 0x40, 0xd0, 0xcb,
0x56, 0x95, 0xcf, 0x82, 0x6f, 0x3f, 0x1f, 0x5e, 0xee, 0xd3, 0x4b, 0xb2, 0x0a, 0xa5, 0x89, 0x7d,
0x42, 0x27, 0x2d, 0xc0, 0x04, 0xfe, 0x61, 0x84, 0xb0, 0xfe, 0x98, 0x86, 0xda, 0x50, 0x06, 0x26,
0xfd, 0xe1, 0x9c, 0x06, 0x21, 0xeb, 0x55, 0x10, 0xda, 0x7e, 0x28, 0x7b, 0x95, 0xe3, 0xbd, 0x42,
0x58, 0xd4, 0x2b, 0xea, 0x8e, 0x25, 0x42, 0x1e, 0x11, 0xaa, 0xd4, 0x1d, 0x8b, 0x64, 0xb6, 0x9a,
0x46, 0x23, 0x1c, 0xfc, 0x82, 0x58, 0x4d, 0xfc, 0xd3, 0x38, 0x00, 0xa2, 0x55, 0xb9, 0x4b, 0x43,
0xdb, 0x99, 0x04, 0xe4, 0x13, 0xa8, 0x87, 0x5a, 0x43, 0x5a, 0xb9, 0xbb, 0x85, 0x7b, 0x35, 0xb5,
0x68, 0xb5, 0x0c, 0x66, 0x0c, 0xcf, 0x38, 0x87, 0xca, 0x1e, 0xa5, 0x07, 0xce, 0xd4, 0x09, 0xc9,
0x3a, 0x94, 0x4e, 0x9d, 0x4b, 0x3a, 0xc6, 0xe6, 0x16, 0xf6, 0x6f, 0x98, 0xfc, 0x93, 0xdc, 0x01,
0xc0, 0x1f, 0xd6, 0x54, 0xad, 0xdf, 0xfd, 0x1b, 0x66, 0x15, 0x61, 0x87, 0x81, 0x1d, 0x92, 0x4d,
0x28, 0xcf, 0xa8, 0x3f, 0xa2, 0x72, 0xa5, 0xec, 0xdf, 0x30, 0x25, 0x60, 0xbb, 0x0c, 0xa5, 0x09,
0x2b, 0xdd, 0xf8, 0x1f, 0x25, 0xa8, 0x0d, 0xa8, 0x3b, 0x96, 0x63, 0x44, 0xa0, 0xc8, 0xa6, 0x00,
0x2b, 0xab, 0x9b, 0xf8, 0x9b, 0xbc, 0x09, 0x35, 0x9c, 0xac, 0x20, 0xf4, 0x1d, 0xf7, 0x8c, 0xef,
0xa3, 0xed, 0x7c, 0x2b, 0x67, 0x02, 0x03, 0x0f, 0x10, 0x4a, 0x9a, 0x50, 0xb0, 0xa7, 0x72, 0x1f,
0xb1, 0x9f, 0xe4, 0x26, 0x54, 0xec, 0x69, 0xc8, 0x9b, 0x57, 0x47, 0x70, 0xd9, 0x9e, 0x86, 0xd8,
0xb4, 0x37, 0xa0, 0x3e, 0xb3, 0xaf, 0xa6, 0xd4, 0x0d, 0xa3, 0x05, 0x58, 0x37, 0x6b, 0x02, 0x86,
0x4b, 0xf0, 0x21, 0xac, 0xe8, 0x28, 0xb2, 0xf2, 0x92, 0xaa, 0x7c, 0x59, 0xc3, 0x16, 0x6d, 0x78,
0x07, 0x96, 0x64, 0x1e, 0x9f, 0xf7, 0x07, 0x17, 0x66, 0xd5, 0x5c, 0x14, 0x60, 0xd9, 0xcb, 0x7b,
0xd0, 0x3c, 0x75, 0x5c, 0x7b, 0x62, 0x8d, 0x26, 0xe1, 0x85, 0x35, 0xa6, 0x93, 0xd0, 0xc6, 0x35,
0x5a, 0x32, 0x17, 0x11, 0xbe, 0x33, 0x09, 0x2f, 0x76, 0x19, 0x94, 0xbc, 0x07, 0xd5, 0x53, 0x4a,
0x2d, 0x1c, 0xac, 0x56, 0x25, 0xb6, 0xd5, 0xe5, 0x0c, 0x99, 0x95, 0x53, 0x39, 0x57, 0xef, 0x41,
0xd3, 0x9b, 0x87, 0x67, 0x9e, 0xe3, 0x9e, 0x59, 0xa3, 0x73, 0xdb, 0xb5, 0x9c, 0x31, 0xae, 0xda,
0xe2, 0x76, 0xfe, 0x41, 0xce, 0x5c, 0x94, 0x69, 0x3b, 0xe7, 0xb6, 0xdb, 0x1d, 0x93, 0xb7, 0x61,
0x69, 0x62, 0x07, 0xa1, 0x75, 0xee, 0xcd, 0xac, 0xd9, 0xfc, 0xe4, 0x19, 0xbd, 0x6a, 0x35, 0x70,
0x20, 0x1a, 0x0c, 0xbc, 0xef, 0xcd, 0x8e, 0x10, 0xc8, 0x16, 0x25, 0xb6, 0x93, 0x37, 0x82, 0x2d,
0xf6, 0x86, 0x59, 0x65, 0x10, 0x5e, 0xe9, 0x53, 0x58, 0xc1, 0xe9, 0x19, 0xcd, 0x83, 0xd0, 0x9b,
0x5a, 0x3e, 0x1d, 0x79, 0xfe, 0x38, 0x68, 0xd5, 0x70, 0xad, 0x7d, 0x5b, 0x34, 0x56, 0x9b, 0xe3,
0xad, 0x5d, 0x1a, 0x84, 0x3b, 0x88, 0x6c, 0x72, 0xdc, 0x8e, 0x1b, 0xfa, 0x57, 0xe6, 0xf2, 0x38,
0x09, 0x27, 0xef, 0x01, 0xb1, 0x27, 0x13, 0xef, 0xb9, 0x15, 0xd0, 0xc9, 0xa9, 0x25, 0x06, 0xb1,
0xb5, 0x78, 0x37, 0x77, 0xaf, 0x62, 0x36, 0x31, 0x65, 0x40, 0x27, 0xa7, 0x47, 0x1c, 0x4e, 0x3e,
0x01, 0xdc, 0xbe, 0xd6, 0x29, 0xb5, 0xc3, 0xb9, 0x4f, 0x83, 0xd6, 0xd2, 0xdd, 0xc2, 0xbd, 0xc5,
0x87, 0xcb, 0x6a, 0xbc, 0x10, 0xbc, 0xed, 0x84, 0x66, 0x9d, 0xe1, 0x89, 0xef, 0x40, 0x5f, 0x0d,
0x8c, 0x1e, 0xb4, 0x9a, 0xb1, 0xd5, 0xc0, 0xa8, 0xc1, 0xe6, 0x2e, 0xac, 0x67, 0xb7, 0x9a, 0xad,
0x3b, 0x36, 0x70, 0x6c, 0xbd, 0x16, 0x4d, 0xf6, 0x93, 0x91, 0x85, 0x0b, 0x7b, 0x32, 0xa7, 0xb8,
0x50, 0xeb, 0x26, 0xff, 0xf8, 0x4e, 0xfe, 0xb3, 0x9c, 0xf1, 0x07, 0x39, 0xa8, 0xf3, 0x81, 0x08,
0x66, 0x9e, 0x1b, 0x50, 0xf2, 0x26, 0x34, 0x64, 0xcd, 0xd4, 0xf7, 0x3d, 0x5f, 0x90, 0x5a, 0xd9,
0x9c, 0x0e, 0x83, 0x91, 0x6f, 0x43, 0x53, 0x22, 0xcd, 0x7c, 0xea, 0x4c, 0xed, 0x33, 0x59, 0xb4,
0x5c, 0x6d, 0x47, 0x02, 0x4c, 0x3e, 0x8c, 0xca, 0xf3, 0xbd, 0x79, 0x48, 0x71, 0x3b, 0xd4, 0x1e,
0xd6, 0xc5, 0x08, 0x98, 0x0c, 0xa6, 0x4a, 0xc7, 0xaf, 0x57, 0xd8, 0x0a, 0xc6, 0x6f, 0xe7, 0x80,
0xb0, 0x66, 0x0f, 0x3d, 0x5e, 0x40, 0x44, 0xce, 0x62, 0x39, 0x73, 0xaf, 0xbc, 0x89, 0xf2, 0x2f,
0xda, 0x44, 0x06, 0x94, 0x78, 0xdb, 0x8b, 0x19, 0x6d, 0xe7, 0x49, 0xdf, 0x2f, 0x56, 0x0a, 0xcd,
0xa2, 0xf1, 0x1f, 0x0b, 0xb0, 0xca, 0x96, 0xb2, 0x4b, 0x27, 0xed, 0xd1, 0x88, 0xce, 0xd4, 0xf6,
0xba, 0x03, 0x35, 0xd7, 0x1b, 0x53, 0xb9, 0xa8, 0x79, 0xc3, 0x80, 0x81, 0xb4, 0x15, 0x7d, 0x6e,
0x3b, 0x2e, 0x6f, 0x38, 0x1f, 0xcc, 0x2a, 0x42, 0xb0, 0xd9, 0x6f, 0xc3, 0xd2, 0x8c, 0xba, 0x63,
0x7d, 0x17, 0x15, 0xf8, 0xc6, 0x10, 0x60, 0xb1, 0x81, 0xee, 0x40, 0xed, 0x74, 0xce, 0xf1, 0x18,
0xed, 0x29, 0xe2, 0x1a, 0x00, 0x01, 0x6a, 0x73, 0x12, 0x34, 0x9b, 0x07, 0xe7, 0x98, 0x5a, 0xc2,
0xd4, 0x32, 0xfb, 0x66, 0x49, 0xb7, 0x01, 0xc6, 0xf3, 0x20, 0x14, 0x9b, 0x6a, 0x01, 0x13, 0xab,
0x0c, 0xc2, 0x37, 0xd5, 0xfb, 0xb0, 0x32, 0xb5, 0x2f, 0x2d, 0x5c, 0x3b, 0x96, 0xe3, 0x5a, 0xa7,
0x13, 0x3c, 0x11, 0xca, 0x88, 0xd7, 0x9c, 0xda, 0x97, 0x5f, 0xb2, 0x94, 0xae, 0xbb, 0x87, 0x70,
0x46, 0x79, 0x46, 0x7c, 0x24, 0x2c, 0x9f, 0x06, 0xd4, 0xbf, 0xa0, 0x48, 0x2c, 0x8a, 0xe6, 0xa2,
0x00, 0x9b, 0x1c, 0xca, 0x5a, 0x34, 0x65, 0xfd, 0x0e, 0x27, 0x23, 0x4e, 0x19, 0xcc, 0xf2, 0xd4,
0x71, 0xf7, 0xc3, 0xc9, 0x88, 0x1d, 0x76, 0x8c, 0xd4, 0xcc, 0xa8, 0x6f, 0x3d, 0x7b, 0x8e, 0xdb,
0xbc, 0x88, 0xa4, 0xe5, 0x88, 0xfa, 0x4f, 0x9e, 0x33, 0x7e, 0x64, 0x14, 0x20, 0xad, 0xb2, 0xaf,
0x5a, 0x35, 0xa4, 0x01, 0x95, 0x51, 0xc0, 0xa8, 0x94, 0x7d, 0xc5, 0xf6, 0x29, 0x6b, 0xad, 0x8d,
0xb3, 0x40, 0xc7, 0x58, 0x7c, 0x80, 0x44, 0xb7, 0x81, 0x8d, 0x6d, 0x8b, 0x04, 0x56, 0x4f, 0xc0,
0x56, 0xbd, 0x6c, 0xec, 0xe9, 0xc4, 0x3e, 0x0b, 0x90, 0xea, 0x34, 0xcc, 0xba, 0x00, 0xee, 0x31,
0x98, 0xf1, 0xe7, 0x79, 0x58, 0x4b, 0x4c, 0xae, 0xd8, 0x34, 0x8c, 0x01, 0x41, 0x08, 0x4e, 0x6c,
0xc5, 0x14, 0x5f, 0x59, 0xb3, 0x96, 0xcf, 0x9a, 0xb5, 0x55, 0x28, 0xf1, 0xcd, 0xc6, 0x8f, 0x50,
0xfe, 0xc1, 0x76, 0xd9, 0x7c, 0x76, 0xea, 0x7b, 0x8c, 0x1f, 0x3b, 0x9f, 0x87, 0x63, 0xef, 0xb9,
0x2b, 0xf8, 0x92, 0x25, 0x01, 0x1f, 0x08, 0x70, 0x7c, 0x28, 0x4a, 0x89, 0xa1, 0xb8, 0x03, 0x35,
0x31, 0x03, 0xc8, 0xd7, 0xf1, 0x89, 0x05, 0x01, 0x62, 0x8c, 0xdd, 0xbb, 0x40, 0xd4, 0x7c, 0x5a,
0x6c, 0xd4, 0xf0, 0x80, 0xe2, 0x13, 0xbb, 0xe4, 0x88, 0x09, 0x3d, 0xb4, 0x2f, 0xf1, 0xa0, 0x7a,
0x0b, 0x16, 0x19, 0x0a, 0x1b, 0x4f, 0x8b, 0x9f, 0xfb, 0x15, 0x3e, 0x56, 0x53, 0xfb, 0x92, 0x0d,
0xe6, 0x0e, 0xb2, 0x5e, 0xaf, 0x43, 0x4d, 0x4e, 0xaa, 0xe5, 0xb8, 0x62, 0x5e, 0xab, 0x62, 0x5e,
0xbb, 0x2e, 0x3b, 0x6e, 0x58, 0x3a, 0x1f, 0x27, 0x6b, 0x4c, 0x67, 0xe1, 0xb9, 0x20, 0xe3, 0x8b,
0x53, 0xc7, 0xe5, 0xc3, 0xbb, 0xcb, 0xa0, 0xc6, 0xef, 0xe4, 0xa0, 0x2e, 0x46, 0x1d, 0xd9, 0x48,
0xb2, 0x05, 0x44, 0x2e, 0xf1, 0xf0, 0xd2, 0x19, 0x5b, 0x27, 0x57, 0x21, 0x0d, 0xf8, 0x8e, 0xda,
0xbf, 0x61, 0x36, 0x45, 0xda, 0xf0, 0xd2, 0x19, 0x6f, 0xb3, 0x14, 0x72, 0x1f, 0x9a, 0x31, 0xfc,
0x20, 0xf4, 0xf9, 0x76, 0xdf, 0xbf, 0x61, 0x2e, 0x6a, 0xd8, 0x83, 0xd0, 0x67, 0x04, 0x84, 0x31,
0xa9, 0xf3, 0xd0, 0x72, 0xdc, 0x31, 0xbd, 0xc4, 0xf9, 0x68, 0x98, 0x35, 0x0e, 0xeb, 0x32, 0xd0,
0xf6, 0x22, 0xd4, 0xf5, 0xe2, 0x8c, 0x33, 0xa8, 0x48, 0x0e, 0x17, 0x59, 0xbc, 0x44, 0x93, 0xcc,
0x6a, 0xa8, 0x5a, 0x72, 0x13, 0x2a, 0xf1, 0x16, 0x98, 0xe5, 0xf0, 0x95, 0x2b, 0x36, 0xbe, 0x0b,
0xcd, 0x03, 0x36, 0x11, 0x2e, 0xdb, 0xc9, 0x82, 0x63, 0x5f, 0x87, 0x05, 0x8d, 0xa2, 0x54, 0x4d,
0xf1, 0xc5, 0x78, 0x96, 0x73, 0x2f, 0x08, 0x45, 0x2d, 0xf8, 0xdb, 0xf8, 0xad, 0x3c, 0x90, 0x4e,
0x10, 0x3a, 0x53, 0x3b, 0xa4, 0x7b, 0x54, 0xd1, 0xcc, 0x3e, 0xd4, 0x59, 0x69, 0x43, 0xaf, 0xcd,
0x59, 0x68, 0xce, 0x90, 0xbd, 0x2b, 0x68, 0x5c, 0x3a, 0xc3, 0x96, 0x8e, 0xcd, 0x8f, 0xc9, 0x58,
0x01, 0x6c, 0xb9, 0x85, 0xb6, 0x7f, 0x46, 0x43, 0x64, 0xbc, 0x05, 0xc7, 0x08, 0x1c, 0xc4, 0x58,
0x6e, 0xb6, 0x58, 0xd9, 0xdc, 0xb3, 0x54, 0xc9, 0x8e, 0x33, 0x0a, 0xc0, 0xd2, 0x02, 0xc6, 0xb3,
0x07, 0x6c, 0x73, 0x58, 0x73, 0x57, 0xf0, 0xed, 0x74, 0x8c, 0xab, 0xbe, 0x62, 0x36, 0x31, 0xe1,
0x38, 0x82, 0x6f, 0xfe, 0x2c, 0x2c, 0xa7, 0x5a, 0xa3, 0x1f, 0x7f, 0xd5, 0x8c, 0xe3, 0xaf, 0xa0,
0x1f, 0x7f, 0xbf, 0x9e, 0x83, 0x95, 0x58, 0x17, 0xc5, 0x86, 0xde, 0x80, 0x32, 0x23, 0x3c, 0x6c,
0x1b, 0xe4, 0xb8, 0x48, 0x71, 0x4a, 0x71, 0xab, 0x7c, 0x04, 0xab, 0xa7, 0x94, 0xfa, 0x76, 0x88,
0x89, 0x48, 0x99, 0xd8, 0x64, 0xf3, 0x92, 0xf9, 0xf9, 0x21, 0xd2, 0x07, 0x76, 0x78, 0x44, 0x7d,
0x36, 0xf1, 0xc4, 0x80, 0x86, 0x44, 0xbe, 0x40, 0xec, 0x02, 0x6e, 0x87, 0x5a, 0x80, 0x28, 0x5f,
0x32, 0x90, 0xf1, 0x27, 0x79, 0x58, 0x62, 0x27, 0xda, 0xa1, 0xed, 0x5e, 0xc9, 0xa9, 0x39, 0xc8,
0x9c, 0x9a, 0x7b, 0x1a, 0xff, 0xa2, 0x61, 0x7f, 0xdd, 0x79, 0x29, 0xa4, 0xe6, 0x25, 0xd5, 0xcc,
0x62, 0xaa, 0x99, 0xe4, 0x2d, 0xa8, 0xc7, 0xfa, 0x5d, 0x52, 0xfd, 0x86, 0x20, 0xea, 0xb0, 0x12,
0x43, 0x16, 0x34, 0x31, 0x24, 0x3e, 0xef, 0xe5, 0x57, 0x99, 0xf7, 0xca, 0x4f, 0x6a, 0xde, 0xdf,
0x86, 0x66, 0x34, 0x7c, 0x62, 0xce, 0x09, 0x14, 0xd9, 0x6e, 0x14, 0x05, 0xe0, 0x6f, 0xe3, 0x1f,
0xe6, 0x39, 0xe2, 0x8e, 0xe7, 0x44, 0x42, 0x13, 0x81, 0x22, 0x32, 0x65, 0x02, 0x91, 0xfd, 0xbe,
0x56, 0x04, 0xfd, 0x29, 0x0e, 0xfa, 0x4d, 0xa8, 0x04, 0x6c, 0x00, 0xed, 0x09, 0x1f, 0xf7, 0x8a,
0x59, 0x66, 0xdf, 0xed, 0xc9, 0x24, 0x9a, 0x8f, 0xf2, 0xb5, 0xf3, 0x51, 0x79, 0x95, 0xf9, 0xa8,
0x66, 0xcf, 0x87, 0xf1, 0x0e, 0x2c, 0x6b, 0xa3, 0xf4, 0x82, 0xf1, 0x3c, 0x07, 0x72, 0xe0, 0x04,
0xe1, 0xb1, 0xcb, 0x8a, 0x50, 0xcc, 0x51, 0xac, 0x21, 0xb9, 0x44, 0x43, 0x58, 0xa2, 0x7d, 0x29,
0x12, 0xf3, 0x22, 0xd1, 0xbe, 0xe4, 0x89, 0xd7, 0x4b, 0x9f, 0x9f, 0xc1, 0x4a, 0xac, 0x26, 0xd1,
0xa8, 0x37, 0xa0, 0x34, 0x0f, 0x2f, 0x3d, 0x29, 0x77, 0xd6, 0xc4, 0x5e, 0x3a, 0x0e, 0x2f, 0x3d,
0x93, 0xa7, 0x18, 0xc7, 0xb0, 0xdc, 0xa3, 0xcf, 0x05, 0x85, 0x95, 0x4d, 0x7c, 0x1b, 0x8a, 0x2f,
0xd1, 0xb1, 0x60, 0xba, 0xde, 0xa0, 0x7c, 0xbc, 0x41, 0x5b, 0x40, 0xf4, 0x62, 0x45, 0x7b, 0x34,
0x65, 0x4c, 0x2e, 0xa6, 0x8c, 0x31, 0xde, 0x06, 0x32, 0x70, 0xce, 0xdc, 0x43, 0x1a, 0x04, 0xf6,
0x99, 0xa2, 0xd6, 0x4d, 0x28, 0x4c, 0x83, 0x33, 0x71, 0xb4, 0xb0, 0x9f, 0xc6, 0x47, 0xb0, 0x12,
0xc3, 0x13, 0x05, 0xbf, 0x06, 0xd5, 0xc0, 0x39, 0x73, 0x51, 0x9e, 0x10, 0x45, 0x47, 0x00, 0x63,
0x0f, 0x56, 0xbf, 0xa4, 0xbe, 0x73, 0x7a, 0xf5, 0xb2, 0xe2, 0xe3, 0xe5, 0xe4, 0x93, 0xe5, 0x74,
0x60, 0x2d, 0x51, 0x8e, 0xa8, 0x9e, 0x6f, 0x3d, 0x31, 0xfb, 0x15, 0x93, 0x7f, 0x68, 0xc7, 0x55,
0x5e, 0x3f, 0xae, 0x0c, 0x0f, 0xc8, 0x8e, 0xe7, 0xba, 0x74, 0x14, 0x1e, 0x51, 0xea, 0xcb, 0xc6,
0xbc, 0xab, 0xed, 0xb3, 0xda, 0xc3, 0x0d, 0x31, 0xe6, 0xc9, 0x33, 0x50, 0x6c, 0x40, 0x02, 0xc5,
0x19, 0xf5, 0xa7, 0x58, 0x70, 0xc5, 0xc4, 0xdf, 0x6c, 0x70, 0x43, 0x67, 0x4a, 0xbd, 0x79, 0x28,
0x28, 0xae, 0xfc, 0x34, 0xd6, 0x60, 0x25, 0x56, 0x21, 0x6f, 0xb5, 0xf1, 0x00, 0xd6, 0x76, 0x9d,
0x60, 0x94, 0x6e, 0xca, 0x06, 0x94, 0x67, 0xf3, 0x13, 0x2b, 0x7e, 0xd0, 0x3e, 0xa1, 0x57, 0x46,
0x0b, 0xd6, 0x93, 0x39, 0x44, 0x59, 0xbf, 0x96, 0x87, 0xe2, 0xfe, 0xf0, 0x60, 0x87, 0x6c, 0x42,
0xc5, 0x71, 0x47, 0xde, 0x94, 0x89, 0x19, 0x7c, 0x34, 0xd4, 0xf7, 0xb5, 0x64, 0xe3, 0x16, 0x54,
0x51, 0x3a, 0x99, 0x78, 0xa3, 0x67, 0x82, 0xd1, 0xaf, 0x30, 0xc0, 0x81, 0x37, 0x7a, 0xc6, 0xb6,
0x26, 0xbd, 0x9c, 0x39, 0x3e, 0x2a, 0xae, 0xa4, 0x62, 0xa6, 0xc8, 0x39, 0xdb, 0x28, 0x21, 0x52,
0xdf, 0x08, 0x26, 0x8c, 0xb1, 0x15, 0x9c, 0xe3, 0xaf, 0x9e, 0x23, 0x13, 0x36, 0xa6, 0x97, 0xe4,
0x7d, 0x20, 0xa7, 0x9e, 0xff, 0xdc, 0xf6, 0x15, 0x93, 0xea, 0x0a, 0xb2, 0x5d, 0x34, 0x97, 0xa3,
0x14, 0xc1, 0x80, 0x91, 0x87, 0xb0, 0xa6, 0xa1, 0x6b, 0x05, 0x73, 0x66, 0x71, 0x25, 0x4a, 0xdc,
0x97, 0x55, 0x18, 0xbf, 0x9a, 0x07, 0x22, 0xf2, 0xef, 0x78, 0x6e, 0x10, 0xfa, 0xb6, 0xe3, 0x86,
0x41, 0x9c, 0x65, 0xcd, 0x25, 0x58, 0xd6, 0x7b, 0xd0, 0x44, 0x86, 0x59, 0xe7, 0x5b, 0xf3, 0x91,
0xf4, 0x60, 0x46, 0xbc, 0xeb, 0x5b, 0xb0, 0x18, 0x09, 0x2d, 0x4a, 0x6f, 0x59, 0x34, 0xeb, 0x4a,
0x70, 0x61, 0x58, 0x1f, 0xc0, 0x2a, 0x23, 0x22, 0x92, 0x19, 0x57, 0x4a, 0x18, 0x4e, 0x6c, 0x97,
0xa7, 0xf6, 0xe5, 0x11, 0x95, 0x22, 0x12, 0x72, 0xb9, 0x06, 0x34, 0x14, 0xff, 0x8a, 0x98, 0x7c,
0xe4, 0x6a, 0x82, 0x83, 0x45, 0x9c, 0x6c, 0x11, 0x63, 0x21, 0x5b, 0xc4, 0x30, 0xfe, 0x5d, 0x15,
0xca, 0x72, 0x18, 0x51, 0x5e, 0x08, 0x9d, 0x0b, 0x1a, 0xc9, 0x0b, 0xec, 0x8b, 0x89, 0x21, 0x3e,
0x9d, 0x7a, 0xa1, 0x92, 0x13, 0xf9, 0x36, 0xa9, 0x73, 0xa0, 0x90, 0x14, 0x35, 0x59, 0x85, 0xab,
0x5b, 0x39, 0xe5, 0x93, 0xb2, 0x0a, 0xe7, 0x44, 0x6f, 0x41, 0x59, 0x4a, 0x1c, 0x45, 0xa5, 0x6d,
0x59, 0x18, 0x71, 0x71, 0x63, 0x13, 0x2a, 0x23, 0x7b, 0x66, 0x8f, 0x9c, 0x90, 0x0b, 0x0b, 0x05,
0x53, 0x7d, 0xb3, 0xd2, 0x27, 0xde, 0xc8, 0x9e, 0x58, 0x27, 0xf6, 0xc4, 0x76, 0x47, 0x54, 0xe8,
0x31, 0xeb, 0x08, 0xdc, 0xe6, 0x30, 0xf2, 0x2d, 0x58, 0x14, 0xed, 0x94, 0x58, 0x5c, 0x9d, 0x29,
0x5a, 0x2f, 0xd1, 0x98, 0x4c, 0xeb, 0x4d, 0xd9, 0xbc, 0x9c, 0x52, 0x2e, 0xfd, 0x15, 0xcc, 0x2a,
0x87, 0xec, 0x51, 0xec, 0xad, 0x48, 0x7e, 0xce, 0xd7, 0x70, 0x95, 0x57, 0xc5, 0x81, 0x5f, 0xf1,
0xf5, 0x9b, 0x16, 0x01, 0x0b, 0x9a, 0x08, 0xf8, 0x2e, 0x2c, 0xcf, 0xdd, 0x80, 0x86, 0xe1, 0x84,
0x8e, 0x55, 0x5b, 0x6a, 0x88, 0xd4, 0x54, 0x09, 0xb2, 0x39, 0x5b, 0xb0, 0xc2, 0x15, 0xb0, 0x81,
0x1d, 0x7a, 0xc1, 0xb9, 0x13, 0x58, 0x01, 0x75, 0xa5, 0x22, 0x6e, 0x19, 0x93, 0x06, 0x22, 0x65,
0xc0, 0x95, 0x37, 0x1b, 0x09, 0x7c, 0x9f, 0x8e, 0xa8, 0x73, 0x41, 0xc7, 0x28, 0x1e, 0x16, 0xcc,
0xb5, 0x58, 0x1e, 0x53, 0x24, 0xa2, 0xac, 0x3f, 0x9f, 0x5a, 0xf3, 0xd9, 0xd8, 0x66, 0x62, 0xc0,
0x22, 0x97, 0xb7, 0xdc, 0xf9, 0xf4, 0x98, 0x43, 0xc8, 0x03, 0x90, 0xf2, 0x9f, 0x58, 0x33, 0x4b,
0xb1, 0xc3, 0x88, 0x51, 0x0d, 0xb3, 0x2e, 0x30, 0xb8, 0x7c, 0x7a, 0x47, 0xdf, 0x2c, 0x4d, 0xb6,
0xc2, 0xf0, 0xf8, 0x8f, 0x36, 0x4c, 0x0b, 0xca, 0x33, 0xdf, 0xb9, 0xb0, 0x43, 0xda, 0x5a, 0xe6,
0x67, 0xbf, 0xf8, 0x64, 0x04, 0xdc, 0x71, 0x9d, 0xd0, 0xb1, 0x43, 0xcf, 0x6f, 0x11, 0x4c, 0x8b,
0x00, 0xe4, 0x3e, 0x2c, 0xe3, 0x3a, 0x09, 0x42, 0x3b, 0x9c, 0x07, 0x42, 0xf8, 0x5d, 0xe1, 0x42,
0x26, 0x4b, 0x18, 0x20, 0x1c, 0xe5, 0x5f, 0xf2, 0x29, 0xac, 0xf3, 0xa5, 0x91, 0xda, 0x9a, 0xab,
0x8a, 0x21, 0x59, 0x41, 0x8c, 0x9d, 0xf8, 0x1e, 0xfd, 0x1c, 0x36, 0xc4, 0x72, 0x49, 0xe5, 0x5c,
0x53, 0x39, 0x57, 0x39, 0x4a, 0x22, 0xeb, 0x16, 0x2c, 0xb3, 0xa6, 0x39, 0x23, 0x4b, 0x94, 0xc0,
0x76, 0xc5, 0x3a, 0xeb, 0x05, 0x66, 0x5a, 0xe2, 0x89, 0x26, 0xa6, 0x3d, 0xa1, 0x57, 0xe4, 0xbb,
0xb0, 0xc4, 0x97, 0x0f, 0x6a, 0x78, 0xf0, 0xc8, 0xde, 0xc4, 0x23, 0x7b, 0x4d, 0x0c, 0xee, 0x8e,
0x4a, 0xc5, 0x53, 0x7b, 0x71, 0x14, 0xfb, 0x66, 0x5b, 0x63, 0xe2, 0x9c, 0x52, 0x76, 0x4e, 0xb4,
0x36, 0xf8, 0x62, 0x93, 0xdf, 0x6c, 0xd7, 0xce, 0x67, 0x98, 0xd2, 0xe2, 0xc4, 0x9a, 0x7f, 0xe1,
0x3a, 0x9e, 0x78, 0x01, 0x95, 0xaa, 0xfb, 0xd6, 0x4d, 0xb1, 0x21, 0x19, 0x50, 0x4a, 0x6a, 0x6f,
0xc3, 0x92, 0xd0, 0xbb, 0x28, 0x03, 0xcb, 0x2d, 0x5c, 0x18, 0x0d, 0xae, 0x7e, 0x91, 0x46, 0x16,
0xc6, 0x30, 0x9e, 0xdb, 0xcf, 0x25, 0x59, 0x7f, 0x0d, 0xa9, 0x09, 0x30, 0x90, 0x20, 0xe8, 0x7b,
0xb0, 0x2c, 0x66, 0x21, 0x22, 0xa6, 0xad, 0xdb, 0x78, 0x44, 0xde, 0x94, 0x7d, 0x4c, 0x51, 0x5b,
0xb3, 0xc9, 0xe7, 0x45, 0xa3, 0xbf, 0xfb, 0x40, 0xe4, 0xa4, 0x68, 0x05, 0xbd, 0xfe, 0xb2, 0x82,
0x96, 0xc5, 0x34, 0x45, 0x20, 0xe3, 0xf7, 0x73, 0x9c, 0xd7, 0x12, 0xd8, 0x81, 0xa6, 0xf3, 0xe2,
0x74, 0xcd, 0xf2, 0xdc, 0xc9, 0x95, 0x20, 0x75, 0xc0, 0x41, 0x7d, 0x77, 0x82, 0xb4, 0xc6, 0x71,
0x75, 0x14, 0x7e, 0x78, 0xd7, 0x25, 0x10, 0x91, 0xee, 0x40, 0x6d, 0x36, 0x3f, 0x99, 0x38, 0x23,
0x8e, 0x52, 0xe0, 0xa5, 0x70, 0x10, 0x22, 0xbc, 0x01, 0x75, 0xb1, 0xd6, 0x39, 0x06, 0x17, 0x16,
0x6b, 0x02, 0x86, 0x28, 0xc8, 0x1c, 0x50, 0x1f, 0x89, 0x5d, 0xdd, 0xc4, 0xdf, 0xc6, 0x36, 0xac,
0xc6, 0x1b, 0x2d, 0x38, 0x97, 0xfb, 0x50, 0x11, 0x94, 0x54, 0x2a, 0x8c, 0x17, 0xe3, 0xa3, 0x61,
0xaa, 0x74, 0xe3, 0xdf, 0x97, 0x60, 0x45, 0x8e, 0x11, 0x9b, 0xec, 0xc1, 0x7c, 0x3a, 0xb5, 0xfd,
0x0c, 0x12, 0x9d, 0x7b, 0x31, 0x89, 0xce, 0xa7, 0x48, 0x74, 0x5c, 0x1d, 0xc8, 0x29, 0x7c, 0x5c,
0x1d, 0xc8, 0x56, 0x17, 0x57, 0x42, 0xe8, 0x16, 0xab, 0x86, 0x00, 0x0f, 0xb9, 0x65, 0x2c, 0x75,
0xa0, 0x94, 0x32, 0x0e, 0x14, 0xfd, 0x38, 0x58, 0x48, 0x1c, 0x07, 0x6f, 0x00, 0x5f, 0xc6, 0x72,
0x3d, 0x96, 0xb9, 0x5e, 0x02, 0x61, 0x62, 0x41, 0xbe, 0x03, 0x4b, 0x49, 0x0a, 0xcc, 0x49, 0xfd,
0x62, 0x06, 0xfd, 0x75, 0xa6, 0x14, 0x99, 0x1a, 0x0d, 0xb9, 0x2a, 0xe8, 0xaf, 0x33, 0xa5, 0x07,
0x98, 0x22, 0xf1, 0x3b, 0x00, 0xbc, 0x6e, 0xdc, 0xc6, 0x80, 0xdb, 0xf8, 0xed, 0xc4, 0xca, 0xd4,
0x46, 0x7d, 0x8b, 0x7d, 0xcc, 0x7d, 0x8a, 0xfb, 0xba, 0x8a, 0x39, 0x71, 0x4b, 0x7f, 0x0a, 0x8b,
0xde, 0x8c, 0xba, 0x56, 0x44, 0x05, 0x6b, 0x58, 0x54, 0x53, 0x14, 0xd5, 0x95, 0x70, 0xb3, 0xc1,
0xf0, 0xd4, 0x27, 0xf9, 0x9c, 0x0f, 0x32, 0xd5, 0x72, 0xd6, 0xaf, 0xc9, 0xb9, 0x88, 0x88, 0x51,
0xd6, 0x8f, 0x50, 0xe5, 0xe6, 0x4d, 0xe6, 0xdc, 0xc8, 0xd5, 0xc0, 0x75, 0x24, 0xb5, 0xfe, 0xa6,
0x4a, 0x31, 0x75, 0x2c, 0xe3, 0x37, 0x72, 0x50, 0xd3, 0xfa, 0x40, 0xd6, 0x60, 0x79, 0xa7, 0xdf,
0x3f, 0xea, 0x98, 0xed, 0x61, 0xf7, 0xcb, 0x8e, 0xb5, 0x73, 0xd0, 0x1f, 0x74, 0x9a, 0x37, 0x18,
0xf8, 0xa0, 0xbf, 0xd3, 0x3e, 0xb0, 0xf6, 0xfa, 0xe6, 0x8e, 0x04, 0xe7, 0xc8, 0x3a, 0x10, 0xb3,
0x73, 0xd8, 0x1f, 0x76, 0x62, 0xf0, 0x3c, 0x69, 0x42, 0x7d, 0xdb, 0xec, 0xb4, 0x77, 0xf6, 0x05,
0xa4, 0x40, 0x56, 0xa1, 0xb9, 0x77, 0xdc, 0xdb, 0xed, 0xf6, 0x1e, 0x5b, 0x3b, 0xed, 0xde, 0x4e,
0xe7, 0xa0, 0xb3, 0xdb, 0x2c, 0x92, 0x06, 0x54, 0xdb, 0xdb, 0xed, 0xde, 0x6e, 0xbf, 0xd7, 0xd9,
0x6d, 0x96, 0x8c, 0x3f, 0xc9, 0x01, 0x44, 0x0d, 0x65, 0x74, 0x35, 0x6a, 0xaa, 0x6e, 0x6e, 0x5e,
0x4b, 0x75, 0x8a, 0xd3, 0x55, 0x3f, 0xf6, 0x4d, 0x1e, 0x42, 0xd9, 0x9b, 0x87, 0x23, 0x6f, 0xca,
0x85, 0x88, 0xc5, 0x87, 0xad, 0x54, 0xbe, 0x3e, 0x4f, 0x37, 0x25, 0x62, 0xcc, 0xa4, 0x5c, 0x78,
0x99, 0x49, 0x39, 0x6e, 0xbb, 0xe6, 0x7c, 0x9d, 0x66, 0xbb, 0xbe, 0x0d, 0x10, 0x3c, 0xa7, 0x74,
0x86, 0x3a, 0x3b, 0xb1, 0x0b, 0xaa, 0x08, 0x19, 0x32, 0xb9, 0xf4, 0x3f, 0xe5, 0x60, 0x0d, 0xd7,
0xd2, 0x38, 0x49, 0xc4, 0xee, 0x42, 0x6d, 0xe4, 0x79, 0x33, 0xca, 0x98, 0x6a, 0xc5, 0xaf, 0xe9,
0x20, 0x46, 0xa0, 0x38, 0x41, 0x3e, 0xf5, 0xfc, 0x11, 0x15, 0x34, 0x0c, 0x10, 0xb4, 0xc7, 0x20,
0x6c, 0x0f, 0x89, 0x4d, 0xc8, 0x31, 0x38, 0x09, 0xab, 0x71, 0x18, 0x47, 0x59, 0x87, 0x85, 0x13,
0x9f, 0xda, 0xa3, 0x73, 0x41, 0xbd, 0xc4, 0x17, 0xf9, 0x76, 0xa4, 0xbb, 0x1c, 0xb1, 0x3d, 0x31,
0xa1, 0xbc, 0xf1, 0x15, 0x73, 0x49, 0xc0, 0x77, 0x04, 0x98, 0x9d, 0xf3, 0xf6, 0x89, 0xed, 0x8e,
0x3d, 0x97, 0x8e, 0x85, 0xfc, 0x1f, 0x01, 0x8c, 0x23, 0x58, 0x4f, 0xf6, 0x4f, 0xd0, 0xbb, 0x4f,
0x34, 0x7a, 0xc7, 0x85, 0xe2, 0xcd, 0xeb, 0xf7, 0x98, 0x46, 0xfb, 0xfe, 0x73, 0x11, 0x8a, 0x4c,
0xe0, 0xb9, 0x56, 0x36, 0xd2, 0x65, 0xdb, 0x42, 0xca, 0xd1, 0x00, 0x55, 0xa4, 0x9c, 0x01, 0x13,
0x93, 0x85, 0x10, 0x64, 0xbc, 0x54, 0xb2, 0x4f, 0x47, 0x17, 0x52, 0x66, 0x41, 0x88, 0x49, 0x47,
0x17, 0xa8, 0xe8, 0xb0, 0x43, 0x9e, 0x97, 0xd3, 0xab, 0x72, 0x60, 0x87, 0x98, 0x53, 0x24, 0x61,
0xbe, 0xb2, 0x4a, 0xc2, 0x5c, 0x2d, 0x28, 0x3b, 0xee, 0x89, 0x37, 0x77, 0xa5, 0x5a, 0x49, 0x7e,
0xa2, 0x5f, 0x03, 0x52, 0x52, 0x76, 0xb4, 0x73, 0x6a, 0x54, 0x61, 0x80, 0x21, 0x3b, 0xdc, 0x3f,
0x84, 0x6a, 0x70, 0xe5, 0x8e, 0x74, 0x1a, 0xb4, 0x2a, 0xc6, 0x87, 0xf5, 0x7e, 0x6b, 0x70, 0xe5,
0x8e, 0x70, 0xc5, 0x57, 0x02, 0xf1, 0x8b, 0x3c, 0x82, 0x8a, 0xb2, 0xf7, 0xf1, 0x13, 0xe4, 0xa6,
0x9e, 0x43, 0x1a, 0xf9, 0xb8, 0x8e, 0x4e, 0xa1, 0x92, 0x0f, 0x60, 0x01, 0xf5, 0xfe, 0x41, 0xab,
0x8e, 0x99, 0xa4, 0xc0, 0xcb, 0x9a, 0x81, 0x2e, 0x05, 0x74, 0x8c, 0xd6, 0x37, 0x53, 0xa0, 0xb1,
0x61, 0x3a, 0x9d, 0xd8, 0x33, 0xa1, 0x85, 0x6f, 0x70, 0xcb, 0x3c, 0x83, 0x70, 0x15, 0xfc, 0x5d,
0xa8, 0xa3, 0x2d, 0x15, 0x71, 0x5c, 0xce, 0x87, 0x16, 0x4c, 0x60, 0xb0, 0xbd, 0x89, 0x3d, 0xeb,
0x05, 0x9b, 0x4f, 0xa0, 0x11, 0x6b, 0x8c, 0xae, 0x42, 0x6b, 0x70, 0x15, 0xda, 0x5b, 0xba, 0x0a,
0x2d, 0x3a, 0x0a, 0x45, 0x36, 0x5d, 0xa5, 0x76, 0x04, 0x15, 0x39, 0x16, 0x8c, 0xe6, 0x1c, 0xf7,
0x9e, 0xf4, 0xfa, 0x5f, 0xf5, 0xac, 0xc1, 0xd3, 0xde, 0x4e, 0xf3, 0x06, 0x59, 0x82, 0x5a, 0x7b,
0x07, 0xc9, 0x18, 0x02, 0x72, 0x0c, 0xe5, 0xa8, 0x3d, 0x18, 0x28, 0x48, 0x9e, 0xa1, 0x1c, 0x75,
0x7b, 0xbd, 0xce, 0x2e, 0x07, 0x14, 0x8c, 0x3d, 0x68, 0x26, 0xfb, 0xce, 0x56, 0x79, 0x28, 0x61,
0xc2, 0xc2, 0x19, 0x01, 0x22, 0x3b, 0x4a, 0x5e, 0xb3, 0xa3, 0x18, 0x8f, 0xa0, 0xc9, 0x4e, 0x7a,
0x36, 0xf8, 0xba, 0xe3, 0xc3, 0x84, 0xf1, 0xe2, 0xba, 0x95, 0xb3, 0x62, 0xd6, 0x38, 0x0c, 0xab,
0x32, 0x3e, 0x81, 0x65, 0x2d, 0x5b, 0xa4, 0x3f, 0x62, 0xdc, 0x43, 0x52, 0x7f, 0x84, 0x92, 0x3f,
0x4f, 0x31, 0x36, 0x60, 0x8d, 0x7d, 0x76, 0x2e, 0xa8, 0x1b, 0x0e, 0xe6, 0x27, 0xdc, 0x5f, 0xc6,
0xf1, 0x5c, 0xe3, 0x57, 0x73, 0x50, 0x55, 0x29, 0xd7, 0x6f, 0x9b, 0x2d, 0xa1, 0x6a, 0xe2, 0x74,
0x72, 0x53, 0xab, 0x01, 0x33, 0x6e, 0xe1, 0xdf, 0x48, 0xe5, 0x64, 0x6c, 0x41, 0x55, 0x81, 0x70,
0x10, 0x3b, 0x1d, 0xd3, 0xea, 0xf7, 0x0e, 0xba, 0x3d, 0x76, 0x5a, 0xb0, 0x71, 0x46, 0xc0, 0xde,
0x1e, 0x42, 0x72, 0x46, 0x13, 0x16, 0x1f, 0xd3, 0xb0, 0xeb, 0x9e, 0x7a, 0x62, 0x30, 0x8c, 0x5f,
0x5f, 0x80, 0x25, 0x05, 0x8a, 0x14, 0x53, 0x17, 0xd4, 0x0f, 0x1c, 0xcf, 0xc5, 0x85, 0x53, 0x35,
0xe5, 0x27, 0xa3, 0x77, 0x42, 0x6c, 0x43, 0xbe, 0x63, 0x15, 0x53, 0x85, 0xa0, 0x87, 0x4c, 0xc7,
0x3b, 0xb0, 0xe4, 0x8c, 0xa9, 0x1b, 0x3a, 0xe1, 0x95, 0x15, 0xb3, 0x4e, 0x2c, 0x4a, 0xb0, 0x60,
0x3c, 0x56, 0xa1, 0x64, 0x4f, 0x1c, 0x5b, 0xfa, 0x21, 0xf1, 0x0f, 0x06, 0x1d, 0x79, 0x13, 0xcf,
0x47, 0x41, 0xa6, 0x6a, 0xf2, 0x0f, 0xf2, 0x00, 0x56, 0x99, 0x50, 0xa5, 0x9b, 0xd3, 0x90, 0x64,
0x71, 0x43, 0x09, 0x71, 0xe7, 0xd3, 0xa3, 0xc8, 0xa4, 0xc6, 0x52, 0x18, 0xbb, 0xc1, 0x72, 0x08,
0xfe, 0x52, 0x65, 0xe0, 0x8a, 0x92, 0x65, 0x77, 0x3e, 0x6d, 0x63, 0x8a, 0xc2, 0x7f, 0x08, 0x6b,
0x0c, 0x5f, 0x71, 0xa4, 0x2a, 0xc7, 0x12, 0xe6, 0x60, 0x85, 0x75, 0x45, 0x9a, 0xca, 0x73, 0x0b,
0xaa, 0xbc, 0x55, 0x6c, 0x49, 0x08, 0xbb, 0x1b, 0x36, 0x85, 0xfa, 0x41, 0xca, 0x65, 0x88, 0x6b,
0x06, 0x92, 0x2e, 0x43, 0x9a, 0xd3, 0x51, 0x25, 0xe9, 0x74, 0xf4, 0x10, 0xd6, 0x4e, 0xd8, 0x1a,
0x3d, 0xa7, 0xf6, 0x98, 0xfa, 0x56, 0xb4, 0xf2, 0xb9, 0xfc, 0xb9, 0xc2, 0x12, 0xf7, 0x31, 0x4d,
0x6d, 0x14, 0xc6, 0x1a, 0x32, 0x4a, 0x44, 0xc7, 0x56, 0xe8, 0x59, 0xc8, 0x31, 0x0a, 0xb5, 0x6d,
0x83, 0x83, 0x87, 0xde, 0x0e, 0x03, 0xc6, 0xf1, 0xce, 0x7c, 0x7b, 0x76, 0x2e, 0xa4, 0x43, 0x85,
0xf7, 0x98, 0x01, 0xc9, 0x6b, 0x50, 0x66, 0x7b, 0xc2, 0xa5, 0xdc, 0xcf, 0x82, 0xcb, 0x5d, 0x12,
0x44, 0xde, 0x82, 0x05, 0xac, 0x23, 0x68, 0x35, 0x71, 0x43, 0xd4, 0xa3, 0xb3, 0xc3, 0x71, 0x4d,
0x91, 0xc6, 0xf8, 0xef, 0xb9, 0xef, 0x70, 0xc2, 0x56, 0x35, 0xf1, 0x37, 0xf9, 0x9e, 0x46, 0x25,
0x57, 0x30, 0xef, 0x5b, 0x22, 0x6f, 0x62, 0x29, 0x5e, 0x47, 0x30, 0xbf, 0x51, 0xf2, 0xf5, 0xfd,
0x62, 0xa5, 0xd6, 0xac, 0x1b, 0x2d, 0xf4, 0x94, 0x32, 0xe9, 0xc8, 0xbb, 0xa0, 0xfe, 0x55, 0x6c,
0x8f, 0xe4, 0x60, 0x23, 0x95, 0x14, 0xf9, 0x4c, 0xf8, 0x02, 0x6e, 0x4d, 0xbd, 0xb1, 0xe4, 0x12,
0xea, 0x12, 0x78, 0xe8, 0x8d, 0x19, 0x37, 0xb3, 0xac, 0x90, 0x4e, 0x1d, 0xd7, 0x09, 0xce, 0xe9,
0x58, 0x30, 0x0b, 0x4d, 0x99, 0xb0, 0x27, 0xe0, 0x8c, 0x25, 0x9f, 0xf9, 0xde, 0x99, 0x3a, 0x3b,
0x73, 0xa6, 0xfa, 0x36, 0x3e, 0x85, 0x12, 0x9f, 0x41, 0xb6, 0x51, 0x70, 0x7e, 0x73, 0x62, 0xa3,
0x20, 0xb4, 0x05, 0x65, 0x97, 0x86, 0xcf, 0x3d, 0xff, 0x99, 0xd4, 0x40, 0x8b, 0x4f, 0xe3, 0x47,
0xa8, 0x65, 0x55, 0x2e, 0x6f, 0x5c, 0x1b, 0xc1, 0x96, 0x30, 0x5f, 0x82, 0xc1, 0xb9, 0x2d, 0x14,
0xbf, 0x15, 0x04, 0x0c, 0xce, 0xed, 0xd4, 0x12, 0xce, 0xa7, 0xbd, 0xde, 0xde, 0x82, 0x45, 0xe9,
0x64, 0x17, 0x58, 0x13, 0x7a, 0x1a, 0x8a, 0x2d, 0x59, 0x17, 0x1e, 0x76, 0xc1, 0x01, 0x3d, 0x0d,
0x8d, 0x43, 0x58, 0x16, 0x9b, 0xa6, 0x3f, 0xa3, 0xb2, 0xea, 0xcf, 0xb2, 0xc4, 0xa4, 0xda, 0xc3,
0x95, 0x38, 0xff, 0xc1, 0x39, 0xbd, 0x98, 0xec, 0x64, 0xfc, 0x20, 0x52, 0x29, 0x32, 0xee, 0x44,
0x94, 0x27, 0x84, 0x15, 0x69, 0x9a, 0x95, 0xee, 0x1f, 0x4a, 0x24, 0x72, 0xc6, 0x6c, 0x74, 0x82,
0xf9, 0x68, 0x24, 0x9d, 0x1f, 0x2b, 0xa6, 0xfc, 0x34, 0xfe, 0x57, 0x0e, 0x56, 0xb0, 0x30, 0x29,
0xe6, 0x89, 0x93, 0xe2, 0xc7, 0x6e, 0x24, 0x9b, 0x1f, 0x9d, 0x25, 0xe4, 0x1f, 0x2f, 0xb7, 0x08,
0x25, 0xad, 0x3d, 0xc5, 0x4c, 0x6b, 0xcf, 0xb7, 0xa1, 0x39, 0xa6, 0x13, 0x07, 0x97, 0x93, 0xe4,
0xb2, 0x38, 0x5b, 0xbb, 0x24, 0xe1, 0x52, 0xf5, 0x90, 0x32, 0x31, 0x2d, 0xa4, 0xcd, 0x8f, 0x7f,
0x33, 0x07, 0xcb, 0x9c, 0xd1, 0x43, 0x85, 0x8f, 0x18, 0xd0, 0x2f, 0xa4, 0x66, 0x43, 0x90, 0x5d,
0xd1, 0xf7, 0x88, 0x01, 0x42, 0x28, 0x47, 0xde, 0xbf, 0x21, 0x34, 0x1e, 0x02, 0x4a, 0xbe, 0x83,
0x22, 0xac, 0x6b, 0x21, 0x50, 0x30, 0xf0, 0x37, 0x33, 0x58, 0x4b, 0x95, 0x9d, 0xc9, 0xb7, 0x2e,
0x82, 0xb6, 0x2b, 0xb0, 0xc0, 0xd5, 0x67, 0xc6, 0x1e, 0x34, 0x62, 0xd5, 0xc4, 0xcc, 0x4a, 0x75,
0x6e, 0x56, 0x4a, 0x59, 0xcf, 0xf3, 0x69, 0xeb, 0xf9, 0x15, 0xac, 0x98, 0xd4, 0x1e, 0x5f, 0xed,
0x79, 0xfe, 0x51, 0x70, 0x12, 0xee, 0x71, 0xee, 0x99, 0x9d, 0x55, 0xca, 0x5f, 0x26, 0x66, 0x87,
0x91, 0x9e, 0x01, 0x72, 0x10, 0xbf, 0x05, 0x8b, 0x91, 0x63, 0x8d, 0xa6, 0xb1, 0x6f, 0x28, 0xdf,
0x1a, 0x64, 0xba, 0x08, 0x14, 0x67, 0xc1, 0x49, 0x28, 0x74, 0xf6, 0xf8, 0xdb, 0xf8, 0x67, 0x25,
0x20, 0x6c, 0xd5, 0x27, 0x16, 0x56, 0x6a, 0x5a, 0x72, 0x69, 0xcb, 0x5f, 0xc2, 0x6d, 0x28, 0x9f,
0x72, 0x1b, 0x7a, 0x00, 0x44, 0x43, 0x90, 0xde, 0x4c, 0x05, 0xe5, 0xcd, 0xd4, 0x8c, 0x70, 0x85,
0x33, 0xd3, 0x03, 0x58, 0x15, 0xe2, 0x4a, 0xbc, 0x3b, 0xb8, 0xcc, 0x4c, 0xc2, 0xe5, 0x96, 0x58,
0x9f, 0xa4, 0xcb, 0x90, 0x54, 0x83, 0x17, 0xb8, 0xcb, 0x90, 0xd4, 0x56, 0x69, 0x8b, 0x79, 0xe1,
0xa5, 0x8b, 0xb9, 0x9c, 0xb9, 0x98, 0x35, 0xed, 0x65, 0x25, 0xae, 0xbd, 0x4c, 0xe9, 0xe1, 0x39,
0x7f, 0x1e, 0xd3, 0xc3, 0xdf, 0x83, 0xa6, 0xd4, 0x64, 0x29, 0x1d, 0xa9, 0xf0, 0x25, 0x11, 0xca,
0x2a, 0xa9, 0x25, 0x8d, 0x19, 0x1a, 0x6b, 0xaf, 0x62, 0xf1, 0xac, 0x67, 0x5b, 0x3c, 0xd3, 0x3a,
0xbf, 0x46, 0x86, 0xce, 0xef, 0x51, 0xe4, 0x2a, 0x12, 0x9c, 0x3b, 0x53, 0x64, 0xa4, 0x22, 0x5f,
0x57, 0x31, 0xc8, 0x83, 0x73, 0x67, 0x6a, 0x4a, 0xa7, 0x2d, 0xf6, 0x41, 0x76, 0xe0, 0x8e, 0xe8,
0x4f, 0x86, 0xbf, 0x15, 0x1f, 0x85, 0x25, 0x5c, 0x2a, 0x9b, 0x1c, 0xed, 0x30, 0xe1, 0x7a, 0x95,
0x18, 0x14, 0xe9, 0xad, 0x13, 0x70, 0xc5, 0xb1, 0x1c, 0x94, 0x43, 0xee, 0xae, 0x83, 0xe4, 0x81,
0xa1, 0x08, 0xa5, 0x62, 0x70, 0x81, 0x7c, 0x57, 0xc3, 0xac, 0x4d, 0xed, 0xcb, 0x03, 0x54, 0x1a,
0x06, 0x17, 0xc6, 0x9f, 0xe7, 0xa0, 0xc9, 0x96, 0x70, 0x8c, 0x3a, 0x7c, 0x0e, 0x48, 0xef, 0x5e,
0x91, 0x38, 0xd4, 0x18, 0xae, 0xa4, 0x0d, 0x9f, 0x02, 0x6e, 0x76, 0xcb, 0x9b, 0x51, 0x57, 0x90,
0x86, 0x56, 0x9c, 0x34, 0x44, 0xc7, 0xc4, 0xfe, 0x0d, 0x2e, 0x75, 0x32, 0x08, 0xf9, 0x1c, 0xaa,
0x6c, 0x4f, 0xe1, 0xe2, 0x15, 0x7e, 0xe6, 0x9b, 0x4a, 0x93, 0x90, 0xda, 0xde, 0x2c, 0xeb, 0x4c,
0x7c, 0x66, 0x39, 0x63, 0x15, 0x33, 0x9c, 0xb1, 0x34, 0xda, 0xb3, 0x0f, 0xf0, 0x84, 0x5e, 0xb1,
0x41, 0x08, 0x3d, 0x9f, 0xf1, 0x6a, 0x6c, 0x8b, 0x9d, 0xda, 0x53, 0x47, 0x68, 0x33, 0x4b, 0x66,
0xf5, 0x19, 0xbd, 0xda, 0x43, 0x00, 0x5b, 0x5b, 0x2c, 0x39, 0x22, 0x40, 0x25, 0xb3, 0xf2, 0x8c,
0x5e, 0x71, 0xea, 0x63, 0x41, 0xe3, 0x09, 0xbd, 0xda, 0xa5, 0x5c, 0x18, 0xf0, 0x7c, 0x36, 0xe8,
0xbe, 0xfd, 0x9c, 0x71, 0xff, 0x31, 0x67, 0xa1, 0x9a, 0x6f, 0x3f, 0x7f, 0x42, 0xaf, 0xa4, 0xe3,
0x52, 0x99, 0xa5, 0x4f, 0xbc, 0x91, 0x60, 0x5f, 0xa4, 0x02, 0x29, 0x6a, 0x94, 0xb9, 0xf0, 0x0c,
0x7f, 0x1b, 0x7f, 0x96, 0x83, 0x06, 0x6b, 0x3f, 0x9e, 0x3c, 0xb8, 0x8a, 0x84, 0xf7, 0x71, 0x2e,
0xf2, 0x3e, 0x7e, 0x28, 0x08, 0x32, 0x3f, 0xc6, 0xf2, 0xd7, 0x1f, 0x63, 0x38, 0x37, 0xfc, 0x0c,
0xfb, 0x10, 0xaa, 0x7c, 0x61, 0x30, 0xf2, 0x53, 0x88, 0x4d, 0x70, 0xac, 0x43, 0x66, 0x05, 0xd1,
0x9e, 0x70, 0x4f, 0x46, 0x4d, 0x57, 0xcf, 0x87, 0xb8, 0xea, 0x2b, 0x0d, 0x7d, 0xc6, 0x34, 0x94,
0xae, 0xf1, 0x64, 0xd4, 0x15, 0xe1, 0x0b, 0x49, 0x45, 0xb8, 0xe1, 0x42, 0x85, 0x4d, 0x35, 0x76,
0x36, 0xa3, 0xd0, 0x5c, 0x56, 0xa1, 0x8c, 0xd9, 0xb1, 0xd9, 0x79, 0xc6, 0x68, 0x74, 0x5e, 0x30,
0x3b, 0x76, 0x40, 0x59, 0x41, 0xac, 0xe1, 0xae, 0x67, 0xa1, 0x66, 0x59, 0xe8, 0x5c, 0x2b, 0x66,
0xd5, 0xf5, 0x8e, 0x38, 0xc0, 0xf8, 0x2b, 0x39, 0xa8, 0x69, 0x7b, 0x16, 0x4d, 0x0d, 0x6a, 0x38,
0xf9, 0x06, 0x8f, 0xef, 0x80, 0xd8, 0x7c, 0xec, 0xdf, 0x30, 0x1b, 0xa3, 0xd8, 0x04, 0x6d, 0x89,
0xa5, 0x8c, 0x39, 0xf3, 0x31, 0xfd, 0x96, 0xec, 0x97, 0x5c, 0xbf, 0xec, 0xf7, 0xf6, 0x02, 0x14,
0x19, 0xaa, 0xf1, 0x05, 0x2c, 0x6b, 0xcd, 0xe0, 0xfa, 0x9f, 0x57, 0x1d, 0x00, 0xe3, 0x17, 0x54,
0x66, 0x56, 0x07, 0xb7, 0xdd, 0x4b, 0xa7, 0x51, 0x3a, 0xe6, 0xe3, 0x22, 0x9c, 0x53, 0x39, 0x08,
0x47, 0xe6, 0x15, 0xfd, 0x18, 0x8d, 0x5f, 0xc9, 0xc1, 0x8a, 0x56, 0xfc, 0x9e, 0xe3, 0xda, 0x13,
0xe7, 0x47, 0x78, 0x8c, 0x05, 0xce, 0x99, 0x9b, 0xa8, 0x80, 0x83, 0xbe, 0x4e, 0x05, 0xe4, 0x2e,
0xd4, 0xb9, 0x97, 0x3a, 0xbf, 0x03, 0x21, 0x8e, 0x59, 0x40, 0x98, 0x69, 0x3f, 0x1f, 0x5e, 0x1a,
0x7f, 0x2b, 0x0f, 0xab, 0xa2, 0x09, 0x78, 0x99, 0xc0, 0x61, 0xac, 0xee, 0x61, 0x70, 0x46, 0x3e,
0x87, 0x06, 0x1b, 0x3e, 0xcb, 0xa7, 0x67, 0x4e, 0x10, 0x52, 0xe9, 0x56, 0x90, 0x41, 0x8d, 0x19,
0x27, 0xc3, 0x50, 0x4d, 0x81, 0x49, 0xbe, 0x80, 0x1a, 0x66, 0xe5, 0x2a, 0x38, 0x31, 0x57, 0xad,
0x74, 0x46, 0x3e, 0x17, 0xfb, 0x37, 0x4c, 0x08, 0xa2, 0x99, 0xf9, 0x02, 0x6a, 0x38, 0xcd, 0x17,
0x38, 0xd6, 0x09, 0x62, 0x97, 0x9a, 0x0b, 0x96, 0x79, 0x16, 0xcd, 0x4c, 0x1b, 0x1a, 0x9c, 0xdc,
0x89, 0x91, 0x14, 0x1e, 0xc8, 0x9b, 0xe9, 0xec, 0x72, 0xac, 0x59, 0xe3, 0x67, 0xda, 0xf7, 0x76,
0x15, 0xca, 0xa1, 0xef, 0x9c, 0x9d, 0x51, 0xdf, 0x58, 0x57, 0x43, 0xc3, 0xe8, 0x38, 0x1d, 0x84,
0x74, 0xc6, 0x64, 0x18, 0xe3, 0x5f, 0xe6, 0xa0, 0x26, 0x28, 0xf3, 0x8f, 0xed, 0xb1, 0xb0, 0x99,
0x50, 0xd6, 0x56, 0x35, 0xdd, 0xec, 0x3b, 0xb0, 0x34, 0x65, 0x02, 0x97, 0x13, 0x5e, 0xc5, 0xdd,
0x15, 0x16, 0x25, 0x58, 0xc8, 0x12, 0x5b, 0xb0, 0x82, 0xa2, 0x45, 0x60, 0x85, 0xce, 0xc4, 0x92,
0x89, 0xe2, 0xae, 0xcd, 0x32, 0x4f, 0x1a, 0x3a, 0x93, 0x43, 0x91, 0xc0, 0x38, 0xec, 0x20, 0xb4,
0xcf, 0xa8, 0xa0, 0x0e, 0xfc, 0x83, 0x09, 0x71, 0x09, 0x5d, 0x80, 0x14, 0xe2, 0xfe, 0xcf, 0x32,
0x6c, 0xa4, 0x92, 0x84, 0x10, 0xa7, 0xac, 0xc3, 0x13, 0x67, 0x7a, 0xe2, 0x29, 0xeb, 0x44, 0x4e,
0xb3, 0x0e, 0x1f, 0xb0, 0x14, 0x69, 0x9d, 0xa0, 0xb0, 0x26, 0x97, 0x2c, 0x9a, 0x17, 0x94, 0xba,
0x20, 0x8f, 0xc2, 0xec, 0x87, 0xf1, 0x63, 0x30, 0x59, 0x9d, 0x84, 0xeb, 0x7c, 0xe1, 0xca, 0x2c,
0x05, 0x0b, 0xc8, 0xff, 0x0f, 0x2d, 0xb5, 0x33, 0x84, 0x6c, 0xa3, 0xe9, 0x3e, 0x58, 0x4d, 0xef,
0xbd, 0xa4, 0xa6, 0x98, 0xde, 0x17, 0x59, 0xaf, 0x75, 0xb9, 0xa9, 0x78, 0x81, 0xaa, 0xae, 0x0b,
0x78, 0x5d, 0xd6, 0x85, 0xb2, 0x4a, 0xba, 0xc6, 0xe2, 0x2b, 0xf5, 0x0d, 0x75, 0xda, 0xb1, 0x6a,
0xcd, 0x5b, 0xa2, 0x60, 0x95, 0xa4, 0xd7, 0x7b, 0x0e, 0xeb, 0xcf, 0x6d, 0x27, 0x94, 0x7d, 0xd4,
0x54, 0x2f, 0x25, 0xac, 0xef, 0xe1, 0x4b, 0xea, 0xfb, 0x8a, 0x67, 0x8e, 0x49, 0x6f, 0xab, 0xcf,
0xd3, 0xc0, 0x60, 0xf3, 0xef, 0x17, 0x60, 0x31, 0x5e, 0x0a, 0x23, 0x3d, 0xe2, 0xb8, 0x92, 0x8c,
0xb4, 0x90, 0x00, 0x84, 0xe5, 0xac, 0xc7, 0x19, 0xe8, 0xb4, 0x4d, 0x2f, 0x9f, 0x61, 0xd3, 0xd3,
0x4d, 0x69, 0x85, 0x97, 0x79, 0x56, 0x14, 0x5f, 0xc9, 0xb3, 0xa2, 0x94, 0xe5, 0x59, 0xf1, 0xd1,
0xb5, 0xa6, 0x78, 0xae, 0x10, 0xcf, 0x34, 0xc3, 0x3f, 0xba, 0xde, 0x0c, 0xcf, 0x75, 0xe5, 0xd7,
0x99, 0xe0, 0x35, 0x07, 0x82, 0xca, 0x35, 0x06, 0x30, 0xcd, 0xa5, 0x20, 0xc3, 0x04, 0x5f, 0xfd,
0x1a, 0x26, 0xf8, 0xcd, 0x3f, 0xcb, 0x01, 0x49, 0xef, 0x0e, 0xf2, 0x98, 0x9b, 0x4b, 0x5d, 0x3a,
0x11, 0x94, 0xfb, 0xfd, 0x57, 0xdb, 0x61, 0x72, 0x41, 0xc8, 0xdc, 0xe4, 0x03, 0x58, 0xd1, 0x6f,
0x04, 0xea, 0xaa, 0x8d, 0x86, 0x49, 0xf4, 0xa4, 0x48, 0x49, 0xa7, 0xb9, 0xb1, 0x14, 0x5f, 0xea,
0xc6, 0x52, 0x7a, 0xa9, 0x1b, 0xcb, 0x42, 0xdc, 0x8d, 0x65, 0xf3, 0xdf, 0xe4, 0x60, 0x25, 0x63,
0x11, 0x7f, 0x73, 0x7d, 0x66, 0x6b, 0x2f, 0x46, 0xd6, 0xf2, 0x62, 0xed, 0xe9, 0x14, 0xed, 0x40,
0x2a, 0x76, 0xd9, 0x54, 0x04, 0xe2, 0xa4, 0xba, 0xff, 0x32, 0xea, 0x12, 0xe5, 0x30, 0xf5, 0xec,
0x9b, 0xff, 0x20, 0x0f, 0x35, 0x2d, 0x91, 0x8d, 0x22, 0x5f, 0xb2, 0x9a, 0x53, 0x28, 0xe7, 0x2d,
0x51, 0x31, 0x83, 0x97, 0x14, 0x70, 0x71, 0x62, 0x3a, 0xdf, 0x5c, 0x82, 0x91, 0x44, 0x84, 0x2d,
0x58, 0x91, 0xa6, 0x6c, 0x1a, 0xb9, 0xdf, 0x8b, 0xb3, 0x46, 0x78, 0x25, 0x88, 0x46, 0x22, 0xfe,
0x07, 0x52, 0xce, 0x8d, 0xe6, 0x4e, 0x33, 0x0d, 0x2e, 0x0b, 0x7f, 0x08, 0x31, 0x89, 0x6c, 0x9d,
0x7f, 0x08, 0x6b, 0xca, 0x21, 0x22, 0x96, 0x83, 0x1b, 0xa0, 0x88, 0x74, 0x7c, 0xd0, 0xb2, 0x7c,
0x0f, 0x6e, 0x27, 0xda, 0x94, 0xc8, 0xca, 0x35, 0x2d, 0x37, 0x63, 0xad, 0xd3, 0x4b, 0xd8, 0xfc,
0x4b, 0xd0, 0x88, 0x11, 0xca, 0x6f, 0x6e, 0xca, 0x93, 0xca, 0x30, 0x3e, 0xa2, 0xba, 0x32, 0x6c,
0xf3, 0x7f, 0x16, 0x80, 0xa4, 0x69, 0xf5, 0x4f, 0xb3, 0x09, 0xe9, 0x85, 0x59, 0xc8, 0x58, 0x98,
0x3f, 0x31, 0xfe, 0x21, 0xd2, 0xc9, 0x6a, 0xfe, 0x08, 0x7c, 0x73, 0x36, 0x55, 0x82, 0x6c, 0xc5,
0xa7, 0x49, 0xaf, 0xad, 0x4a, 0xec, 0xea, 0xaa, 0xc6, 0x40, 0x25, 0x9c, 0xb7, 0x8e, 0x61, 0xc1,
0x76, 0x47, 0xe7, 0x9e, 0x2f, 0xe8, 0xe0, 0xcf, 0x7c, 0xed, 0xe3, 0x73, 0xab, 0x8d, 0xf9, 0x91,
0x6b, 0x33, 0x45, 0x61, 0xc6, 0x87, 0x50, 0xd3, 0xc0, 0xa4, 0x0a, 0xa5, 0x83, 0xee, 0xe1, 0x76,
0xbf, 0x79, 0x83, 0x34, 0xa0, 0x6a, 0x76, 0x76, 0xfa, 0x5f, 0x76, 0xcc, 0xce, 0x6e, 0x33, 0x47,
0x2a, 0x50, 0x3c, 0xe8, 0x0f, 0x86, 0xcd, 0xbc, 0xb1, 0x09, 0x2d, 0x51, 0x62, 0xda, 0x3a, 0xf5,
0xdb, 0x45, 0xa5, 0x53, 0xc5, 0x44, 0x21, 0xe4, 0x7f, 0x04, 0x75, 0x9d, 0xbd, 0x11, 0x2b, 0x22,
0xe1, 0x12, 0xc3, 0xc4, 0x7b, 0x4f, 0xa3, 0xd5, 0x3b, 0xc0, 0x1d, 0x22, 0xc6, 0x2a, 0x5b, 0x3e,
0xc6, 0xb7, 0x66, 0x58, 0x96, 0x51, 0x3e, 0x8a, 0x2d, 0xc3, 0xff, 0x0f, 0x16, 0xe3, 0x96, 0x18,
0x41, 0x91, 0xb2, 0x44, 0x56, 0x96, 0x3b, 0x66, 0x9a, 0x21, 0xdf, 0x83, 0x66, 0xd2, 0x92, 0x23,
0x98, 0xe7, 0x6b, 0xf2, 0x2f, 0x39, 0x71, 0xe3, 0x0e, 0xd9, 0x87, 0xd5, 0x2c, 0x06, 0x0f, 0xd7,
0xc7, 0xf5, 0x6a, 0x0e, 0x92, 0x66, 0xe2, 0xc8, 0x67, 0xc2, 0xa2, 0x57, 0xc2, 0xe9, 0x7f, 0x2b,
0x5e, 0xbf, 0x36, 0xd8, 0x5b, 0xfc, 0x9f, 0x66, 0xdb, 0xbb, 0x00, 0x88, 0x60, 0xa4, 0x09, 0xf5,
0xfe, 0x51, 0xa7, 0x67, 0xed, 0xec, 0xb7, 0x7b, 0xbd, 0xce, 0x41, 0xf3, 0x06, 0x21, 0xb0, 0x88,
0x5e, 0x1d, 0xbb, 0x0a, 0x96, 0x63, 0x30, 0x61, 0x6a, 0x95, 0xb0, 0x3c, 0x59, 0x85, 0x66, 0xb7,
0x97, 0x80, 0x16, 0x48, 0x0b, 0x56, 0x8f, 0x3a, 0xdc, 0x11, 0x24, 0x56, 0x6e, 0x91, 0x09, 0x0d,
0xa2, 0xbb, 0x46, 0x08, 0xab, 0x5f, 0xd9, 0x93, 0x09, 0x0d, 0xdb, 0xdc, 0x91, 0x5d, 0x6e, 0x87,
0x77, 0x61, 0x59, 0xa9, 0xc3, 0x12, 0xdc, 0x72, 0x53, 0x25, 0x48, 0xe4, 0x0f, 0x60, 0x45, 0xd3,
0xaa, 0x25, 0x4e, 0x21, 0xa2, 0x25, 0x89, 0x0c, 0x4c, 0x54, 0xe1, 0xb5, 0x0a, 0x80, 0xe4, 0xe0,
0xff, 0x28, 0x0f, 0x6b, 0x89, 0x84, 0xc8, 0x08, 0xc3, 0xf9, 0xf7, 0x78, 0x5b, 0xea, 0x08, 0x7c,
0x61, 0xa3, 0xf3, 0x5f, 0xaf, 0xd1, 0x85, 0xeb, 0x1a, 0x4d, 0x9e, 0xc2, 0x92, 0xf0, 0xf6, 0xd7,
0x78, 0x3c, 0x46, 0x23, 0x1e, 0x88, 0x29, 0xcf, 0x6c, 0xf9, 0x56, 0x7c, 0x60, 0xb9, 0x95, 0x6b,
0xd1, 0x8e, 0x01, 0x37, 0x7f, 0x09, 0x56, 0x32, 0xd0, 0x32, 0xee, 0xbc, 0x7c, 0x18, 0xb7, 0x78,
0xdd, 0x8a, 0xd5, 0x1c, 0x2f, 0x42, 0xb7, 0xde, 0x6f, 0xc1, 0x82, 0xd0, 0xf6, 0x36, 0xa1, 0x20,
0xaf, 0x3d, 0x15, 0x4d, 0xf6, 0x93, 0x10, 0x28, 0x4e, 0x23, 0x07, 0x6c, 0xfc, 0x6d, 0x6c, 0xa8,
0xab, 0x90, 0x89, 0x09, 0xfa, 0x95, 0x22, 0xac, 0x27, 0x53, 0xd4, 0x95, 0x84, 0x72, 0x6c, 0x6e,
0xb8, 0x25, 0x51, 0x80, 0xc8, 0xc7, 0x89, 0xed, 0x16, 0x9b, 0x1d, 0x44, 0xd5, 0xb7, 0x96, 0x1c,
0xf2, 0x87, 0x49, 0xa6, 0x9a, 0xd3, 0x88, 0x86, 0xbc, 0xa0, 0x81, 0x7d, 0x4a, 0xf0, 0xd8, 0x1f,
0xa7, 0x78, 0xec, 0x62, 0x56, 0xa6, 0x04, 0xcb, 0xdd, 0x81, 0x8d, 0xc8, 0xd5, 0x38, 0x5e, 0x67,
0x29, 0x2b, 0xfb, 0x9a, 0xc2, 0x3e, 0xd0, 0x2b, 0x7f, 0x0c, 0xad, 0xa8, 0x98, 0x44, 0x33, 0x16,
0xb2, 0xca, 0x59, 0x57, 0xe8, 0x66, 0xac, 0x3d, 0xdf, 0x87, 0xcd, 0xd8, 0x78, 0xc5, 0x9b, 0x54,
0xce, 0x2a, 0x6a, 0x43, 0x1b, 0xc0, 0x58, 0xa3, 0x0e, 0xe0, 0x56, 0xac, 0xac, 0x44, 0xbb, 0x2a,
0x59, 0x85, 0xb5, 0xb4, 0xc2, 0x62, 0x2d, 0x33, 0x7e, 0x77, 0x01, 0xc8, 0x0f, 0xe6, 0xd4, 0xbf,
0xc2, 0x0b, 0xd2, 0xc1, 0xcb, 0xee, 0x50, 0x48, 0x4d, 0x65, 0xfe, 0x95, 0xe2, 0x24, 0x64, 0xc5,
0x29, 0x28, 0xbe, 0x3c, 0x4e, 0x41, 0xe9, 0x65, 0x71, 0x0a, 0xde, 0x84, 0x86, 0x73, 0xe6, 0x7a,
0x8c, 0x11, 0x60, 0x72, 0x60, 0xd0, 0x5a, 0xb8, 0x5b, 0xb8, 0x57, 0x37, 0xeb, 0x02, 0xc8, 0xa4,
0xc0, 0x80, 0x7c, 0x11, 0x21, 0xd1, 0xf1, 0x19, 0x46, 0xf1, 0xd0, 0x59, 0x80, 0xce, 0xf8, 0x8c,
0x0a, 0xc5, 0x2c, 0x2e, 0x58, 0x99, 0x99, 0xc1, 0x03, 0xf2, 0x16, 0x2c, 0x06, 0xde, 0x9c, 0x89,
0xd5, 0x72, 0x18, 0xb8, 0xbd, 0xbf, 0xce, 0xa1, 0x47, 0xd2, 0xfb, 0x63, 0x65, 0x1e, 0x50, 0x6b,
0xea, 0x04, 0x01, 0x13, 0x4e, 0x46, 0x9e, 0x1b, 0xfa, 0xde, 0x44, 0x98, 0xf0, 0x97, 0xe7, 0x01,
0x3d, 0xe4, 0x29, 0x3b, 0x3c, 0x81, 0x7c, 0x1c, 0x35, 0x69, 0x66, 0x3b, 0x7e, 0xd0, 0x02, 0x6c,
0x92, 0xec, 0x29, 0x4a, 0xaf, 0xb6, 0xe3, 0xab, 0xb6, 0xb0, 0x8f, 0x20, 0x11, 0x3f, 0xa1, 0x96,
0x8c, 0x9f, 0xf0, 0xcb, 0xd9, 0xf1, 0x13, 0x1a, 0x31, 0x62, 0x96, 0x9e, 0xe2, 0xaf, 0x15, 0x46,
0x21, 0x1d, 0x16, 0x62, 0xf1, 0xeb, 0x84, 0x85, 0x58, 0xca, 0x0a, 0x0b, 0xf1, 0x21, 0xd4, 0xf0,
0x36, 0xbe, 0x75, 0x8e, 0xce, 0xcc, 0xdc, 0x25, 0xa1, 0xa9, 0x5f, 0xd7, 0xdf, 0x77, 0xdc, 0xd0,
0x04, 0x5f, 0xfe, 0x0c, 0xd2, 0x11, 0x1a, 0x96, 0x5f, 0x29, 0x42, 0xc3, 0x37, 0x13, 0x7e, 0x41,
0x44, 0x0d, 0xd8, 0x82, 0x8a, 0x9c, 0x27, 0x46, 0x6c, 0x4f, 0x7d, 0x6f, 0x2a, 0xcd, 0x9b, 0xec,
0x37, 0x59, 0x84, 0x7c, 0xe8, 0x89, 0xcc, 0xf9, 0xd0, 0x33, 0x7e, 0x11, 0x6a, 0xda, 0x52, 0x23,
0x6f, 0x70, 0xbd, 0xbe, 0x4b, 0x27, 0x52, 0xed, 0xcb, 0x47, 0xb1, 0x2a, 0xa0, 0xdd, 0x31, 0x3b,
0xf7, 0xc6, 0x8e, 0x4f, 0x31, 0x96, 0x8a, 0xe5, 0xd3, 0x0b, 0xea, 0x07, 0xd2, 0x2c, 0xdd, 0x54,
0x09, 0x26, 0x87, 0x1b, 0xbf, 0x04, 0x2b, 0xb1, 0xb9, 0x15, 0xe4, 0xfb, 0x2d, 0x58, 0xc0, 0x71,
0x93, 0xbe, 0x4f, 0xf1, 0x30, 0x08, 0x22, 0x0d, 0x23, 0xca, 0x70, 0x8b, 0xba, 0x35, 0xf3, 0xbd,
0x13, 0xac, 0x24, 0x67, 0xd6, 0x04, 0xec, 0xc8, 0xf7, 0x4e, 0x8c, 0xbf, 0x56, 0x84, 0xc2, 0xbe,
0x37, 0xd3, 0x1d, 0xa0, 0x73, 0x29, 0x07, 0x68, 0xa1, 0x6e, 0xb1, 0x94, 0x3a, 0x45, 0x48, 0xac,
0x68, 0x23, 0x96, 0x2a, 0x95, 0x7b, 0xb0, 0xc8, 0xe8, 0x44, 0xe8, 0x59, 0xe2, 0xe2, 0x11, 0x3f,
0x9c, 0xf9, 0xe6, 0xb3, 0xa7, 0xe1, 0xd0, 0xdb, 0xe3, 0x70, 0xb2, 0x0a, 0x05, 0x25, 0xbc, 0x63,
0x32, 0xfb, 0x24, 0xeb, 0xb0, 0x80, 0x17, 0xa6, 0xe4, 0x9d, 0x79, 0xf1, 0x45, 0xde, 0x87, 0x95,
0x78, 0xb9, 0x9c, 0x14, 0x09, 0xc9, 0x40, 0x2f, 0x18, 0x69, 0xd2, 0x4d, 0x60, 0x74, 0x24, 0xba,
0x35, 0x5f, 0x30, 0xcb, 0xa7, 0x94, 0x62, 0x92, 0x46, 0xf4, 0x2a, 0x31, 0xa2, 0x77, 0x07, 0x6a,
0xe1, 0xe4, 0xc2, 0x9a, 0xd9, 0x57, 0x13, 0xcf, 0x96, 0x37, 0x2b, 0x21, 0x9c, 0x5c, 0x1c, 0x71,
0x08, 0xf9, 0x00, 0x60, 0x3a, 0x9b, 0x89, 0xbd, 0x87, 0xf6, 0xcc, 0x68, 0x29, 0x1f, 0x1e, 0x1d,
0xf1, 0x25, 0x67, 0x56, 0xa7, 0xb3, 0x19, 0xff, 0xc9, 0x32, 0xd8, 0x53, 0x95, 0xa1, 0x1e, 0xcb,
0xd0, 0x3e, 0x54, 0x19, 0xec, 0xa9, 0xcc, 0xb0, 0x0b, 0x8b, 0x99, 0x01, 0x52, 0x6e, 0xcb, 0x7b,
0x28, 0xde, 0x6c, 0x2b, 0x63, 0x37, 0x37, 0x46, 0x3a, 0x6c, 0xf3, 0x7b, 0x40, 0xfe, 0x82, 0x31,
0x48, 0x86, 0x50, 0x55, 0x1d, 0x4a, 0x45, 0x3e, 0xa9, 0xa5, 0x22, 0x9f, 0x30, 0x42, 0xca, 0x39,
0x3d, 0x75, 0x46, 0x80, 0xc6, 0xea, 0x89, 0x1b, 0x5c, 0xc6, 0x09, 0x54, 0x55, 0xaf, 0xd1, 0x26,
0xe5, 0x79, 0xa1, 0x15, 0x9c, 0xdb, 0xe2, 0x3a, 0x64, 0xdd, 0xac, 0x32, 0xc8, 0x80, 0x01, 0xc8,
0x1a, 0x2c, 0x04, 0x34, 0x8c, 0xac, 0x0e, 0xa5, 0x80, 0x86, 0xdc, 0x04, 0x35, 0x3a, 0x77, 0x26,
0xe3, 0xd8, 0x9d, 0x7c, 0x40, 0x10, 0x37, 0xeb, 0xfd, 0x97, 0x1c, 0x94, 0x78, 0xcc, 0x92, 0xb7,
0x61, 0x89, 0xb7, 0x49, 0x79, 0xb8, 0x0b, 0x37, 0x24, 0xce, 0x94, 0x0e, 0x85, 0x73, 0x3b, 0xdb,
0xab, 0x5a, 0x10, 0xa8, 0x88, 0xb7, 0xd1, 0x02, 0x41, 0xdd, 0x81, 0xaa, 0xea, 0x9e, 0xb6, 0x9e,
0x2b, 0xb2, 0x77, 0xe4, 0x75, 0x28, 0x9e, 0x7b, 0x33, 0xa9, 0x8c, 0x85, 0x68, 0xb6, 0x4c, 0x84,
0x47, 0x6d, 0x61, 0x75, 0x44, 0xb7, 0xd7, 0x0a, 0xa2, 0x2d, 0xac, 0x12, 0x19, 0xc9, 0x21, 0x31,
0x8e, 0x0b, 0x19, 0xe3, 0x78, 0x0c, 0x4b, 0x8c, 0x38, 0x69, 0xbe, 0x50, 0xd7, 0x9f, 0xe4, 0xdf,
0x66, 0x42, 0xd7, 0x68, 0x32, 0x1f, 0x53, 0x5d, 0x1d, 0x8e, 0xee, 0xca, 0x02, 0x2e, 0x85, 0x5d,
0xe3, 0x77, 0x73, 0x9c, 0xe8, 0xb1, 0x72, 0xc9, 0x3d, 0x28, 0xba, 0xd2, 0x6f, 0x2a, 0x12, 0xad,
0xd4, 0x4d, 0x4f, 0x86, 0x67, 0x22, 0x06, 0x5b, 0x1e, 0xe8, 0x6d, 0xa4, 0x97, 0xde, 0x30, 0x6b,
0xee, 0x7c, 0xaa, 0xb4, 0xc9, 0xdf, 0x92, 0xdd, 0x4a, 0x68, 0x62, 0x79, 0xef, 0x15, 0xed, 0xd8,
0xd2, 0xfc, 0x9e, 0x8b, 0xb1, 0x63, 0x5c, 0x0a, 0x66, 0xe3, 0x33, 0xaa, 0xf9, 0x3b, 0xff, 0x41,
0x1e, 0x1a, 0xb1, 0x16, 0xa1, 0xe3, 0x37, 0x3b, 0x95, 0xb8, 0xb5, 0x58, 0xcc, 0x37, 0xfa, 0xd7,
0x0a, 0xd9, 0x59, 0x1b, 0xa7, 0x7c, 0x6c, 0x9c, 0x94, 0xe3, 0x63, 0x41, 0x77, 0x7c, 0x7c, 0x00,
0xd5, 0x28, 0xf8, 0x57, 0xbc, 0x49, 0xac, 0x3e, 0x79, 0xdf, 0x35, 0x42, 0x8a, 0x5c, 0x25, 0x4b,
0xba, 0xab, 0xe4, 0x77, 0x35, 0xcf, 0xba, 0x05, 0x2c, 0xc6, 0xc8, 0x1a, 0xd1, 0x9f, 0x8a, 0x5f,
0x9d, 0xf1, 0x05, 0xd4, 0xb4, 0xc6, 0xeb, 0xde, 0x69, 0xb9, 0x98, 0x77, 0x9a, 0xba, 0x55, 0x9f,
0x8f, 0x6e, 0xd5, 0x1b, 0xbf, 0x96, 0x87, 0x06, 0xdb, 0x5f, 0x8e, 0x7b, 0x76, 0xe4, 0x4d, 0x9c,
0x11, 0x5a, 0x8f, 0xd5, 0x0e, 0x13, 0xdc, 0x9f, 0xdc, 0x67, 0x62, 0x8b, 0x71, 0xe6, 0x4f, 0x0f,
0x2a, 0xc3, 0x4f, 0x0e, 0x15, 0x54, 0xc6, 0x80, 0x06, 0xa3, 0xd6, 0x68, 0x07, 0x8e, 0x02, 0x85,
0x99, 0xb5, 0x53, 0x4a, 0xb7, 0xed, 0x80, 0x93, 0xed, 0xf7, 0x61, 0x85, 0xe1, 0x60, 0x9c, 0x87,
0xa9, 0x33, 0x99, 0x38, 0xd1, 0x75, 0xd1, 0x82, 0xd9, 0x3c, 0xa5, 0xd4, 0xb4, 0x43, 0x7a, 0xc8,
0x12, 0x44, 0x5c, 0xb1, 0xca, 0xd8, 0x09, 0xec, 0x93, 0xc8, 0x3d, 0x5f, 0x7d, 0x4b, 0xf7, 0x8a,
0xc8, 0x83, 0x45, 0x78, 0x5f, 0x89, 0x70, 0x29, 0x98, 0x3f, 0xb1, 0x92, 0xca, 0xc9, 0x95, 0x64,
0xfc, 0xd3, 0x3c, 0xd4, 0xb4, 0x65, 0xf9, 0x2a, 0x47, 0xfe, 0xed, 0x94, 0xb5, 0xbf, 0xaa, 0x1b,
0xf6, 0xdf, 0x8c, 0x57, 0x59, 0x50, 0x77, 0x0a, 0xf5, 0x05, 0x7c, 0x0b, 0xaa, 0x6c, 0xd7, 0x7d,
0x88, 0x56, 0x11, 0x11, 0xf1, 0x0f, 0x01, 0x47, 0xf3, 0x13, 0x99, 0xf8, 0x10, 0x13, 0x4b, 0x51,
0xe2, 0x43, 0x96, 0xf8, 0xa2, 0x3b, 0x45, 0x9f, 0x42, 0x5d, 0x94, 0x8a, 0x73, 0x2a, 0x64, 0x95,
0x55, 0x8d, 0x9d, 0x50, 0xf3, 0x6d, 0xd6, 0x78, 0x75, 0x7c, 0xf2, 0x45, 0xc6, 0x87, 0x32, 0x63,
0xe5, 0x65, 0x19, 0x1f, 0xf2, 0x0f, 0x63, 0x4f, 0x5d, 0xd3, 0x42, 0x9f, 0x56, 0x49, 0xc7, 0x3e,
0x80, 0x15, 0x49, 0xae, 0xe6, 0xae, 0xed, 0xba, 0xde, 0xdc, 0x1d, 0x51, 0x79, 0x65, 0x9d, 0x88,
0xa4, 0xe3, 0x28, 0xc5, 0x18, 0xab, 0x50, 0x34, 0xdc, 0x37, 0xf6, 0x3e, 0x94, 0xb8, 0xb0, 0xc0,
0x39, 0xa2, 0x6c, 0xc2, 0xc5, 0x51, 0xc8, 0x3d, 0x28, 0x71, 0x99, 0x21, 0x7f, 0x2d, 0xb1, 0xe1,
0x08, 0x46, 0x1b, 0x08, 0xcb, 0x78, 0x48, 0x43, 0xdf, 0x19, 0x05, 0xd1, 0x6d, 0xf8, 0x52, 0x78,
0x35, 0x13, 0x75, 0x45, 0xc6, 0x94, 0x08, 0x13, 0xd5, 0x46, 0x1c, 0x87, 0x1d, 0x4c, 0x2b, 0xb1,
0x32, 0x04, 0x0f, 0x37, 0x81, 0xf5, 0x13, 0x1a, 0x3e, 0xa7, 0xd4, 0x75, 0x19, 0x87, 0x36, 0xa2,
0x6e, 0xe8, 0xdb, 0x13, 0x36, 0x49, 0xbc, 0x07, 0x8f, 0x52, 0xa5, 0x46, 0x6a, 0xc9, 0xed, 0x28,
0xe3, 0x8e, 0xca, 0xc7, 0x69, 0xc7, 0xda, 0x49, 0x56, 0xda, 0xe6, 0x2f, 0xc0, 0xe6, 0xf5, 0x99,
0x32, 0x74, 0x17, 0xf7, 0xe2, 0x54, 0x45, 0x99, 0xe6, 0x27, 0x9e, 0x1d, 0xf2, 0xd6, 0xe8, 0x94,
0xa5, 0x07, 0x35, 0x2d, 0x25, 0xe2, 0x2f, 0x72, 0xc8, 0x71, 0xf2, 0x0f, 0x76, 0x22, 0xb9, 0x9e,
0x3f, 0x45, 0x53, 0xf8, 0xd8, 0x8a, 0x4a, 0xcf, 0x99, 0x4b, 0x11, 0x1c, 0xbd, 0xa7, 0x8c, 0x2d,
0x58, 0x42, 0x71, 0x43, 0x3b, 0xe8, 0x5e, 0xc4, 0xa1, 0x1a, 0xab, 0x40, 0x7a, 0x9c, 0x76, 0xe9,
0x7e, 0xc2, 0x7f, 0x54, 0x80, 0x9a, 0x06, 0x66, 0xa7, 0x11, 0x3a, 0x57, 0x5b, 0x63, 0xc7, 0x9e,
0x52, 0xe9, 0x77, 0xd0, 0x30, 0x1b, 0x08, 0xdd, 0x15, 0x40, 0x76, 0x16, 0xdb, 0x17, 0x67, 0x96,
0x37, 0x0f, 0xad, 0x31, 0x3d, 0xf3, 0xa9, 0x6c, 0x65, 0xdd, 0xbe, 0x38, 0xeb, 0xcf, 0xc3, 0x5d,
0x84, 0xc9, 0xd8, 0x4b, 0x1a, 0x56, 0x41, 0xc5, 0x5e, 0x8a, 0xb0, 0x84, 0x53, 0x3a, 0x5f, 0x99,
0x45, 0xe5, 0x94, 0xce, 0x45, 0xd8, 0xe4, 0x01, 0x5a, 0x4a, 0x1f, 0xa0, 0x1f, 0xc3, 0x3a, 0x3f,
0x40, 0x05, 0x69, 0xb6, 0x12, 0x3b, 0x79, 0x15, 0x53, 0x45, 0x27, 0x35, 0x5e, 0xbc, 0xc9, 0x7a,
0x20, 0xc9, 0x52, 0xe0, 0xfc, 0x88, 0x13, 0xb2, 0x9c, 0xc9, 0x7a, 0x26, 0x0a, 0x1f, 0x38, 0x3f,
0xa2, 0x32, 0xf6, 0x53, 0x0c, 0x53, 0xdc, 0x18, 0x9c, 0x3a, 0x6e, 0x12, 0xd3, 0xbe, 0x8c, 0x63,
0x56, 0x05, 0xa6, 0x7d, 0xa9, 0x63, 0x3e, 0x82, 0x8d, 0x29, 0x1d, 0x3b, 0x76, 0xbc, 0x58, 0x2b,
0x62, 0x0e, 0x57, 0x79, 0xb2, 0x96, 0x67, 0xc0, 0xb5, 0x09, 0x6c, 0x34, 0x7e, 0xe4, 0x4d, 0x4f,
0x1c, 0xce, 0xb3, 0x70, 0xbf, 0xc0, 0xa2, 0xb9, 0xe8, 0xce, 0xa7, 0x3f, 0x8f, 0x60, 0x96, 0x25,
0x30, 0x1a, 0x50, 0x1b, 0x84, 0xde, 0x4c, 0x4e, 0xf3, 0x22, 0xd4, 0xf9, 0xa7, 0x88, 0xf6, 0x70,
0x0b, 0x6e, 0x22, 0x49, 0x18, 0x7a, 0x33, 0x6f, 0xe2, 0x9d, 0x5d, 0xc5, 0x54, 0xeb, 0xff, 0x2a,
0x07, 0x2b, 0xb1, 0x54, 0x41, 0x5e, 0x3f, 0xe6, 0xf4, 0x4c, 0xdd, 0x14, 0xcf, 0xc5, 0xae, 0x09,
0xb2, 0xf9, 0xe2, 0x88, 0x9c, 0x98, 0xc9, 0xdb, 0xe3, 0xed, 0x28, 0xb0, 0x9a, 0xcc, 0xc8, 0x49,
0x4a, 0x2b, 0x4d, 0x52, 0x44, 0x7e, 0x19, 0x72, 0x4d, 0x16, 0xf1, 0x33, 0xe2, 0x56, 0xe7, 0x58,
0x74, 0xb9, 0x10, 0xbf, 0xf7, 0xa5, 0xab, 0xe1, 0x65, 0x0b, 0x22, 0xdd, 0x7c, 0x60, 0xfc, 0x69,
0x1e, 0x20, 0x6a, 0x1d, 0xb9, 0xab, 0xf3, 0x2d, 0xac, 0x0f, 0xdc, 0xf5, 0x54, 0xe3, 0x53, 0xde,
0x80, 0xba, 0xba, 0x11, 0x12, 0x71, 0x43, 0x35, 0x09, 0x63, 0x2c, 0xd1, 0xbb, 0xb0, 0x74, 0x36,
0xf1, 0x4e, 0x90, 0x6b, 0x15, 0xbc, 0x0b, 0x3a, 0xf7, 0x60, 0x51, 0x8b, 0x3c, 0x49, 0x85, 0x47,
0x54, 0xfc, 0x53, 0x31, 0xf3, 0xe2, 0x48, 0x8c, 0x1b, 0xfa, 0x1c, 0x16, 0x71, 0x90, 0xa3, 0x26,
0x96, 0xaf, 0x65, 0xad, 0x1a, 0x6e, 0xf4, 0x81, 0xea, 0x9e, 0x24, 0x23, 0x75, 0x27, 0x35, 0x37,
0x3f, 0x1d, 0x2e, 0xea, 0xb7, 0xf2, 0xca, 0x7f, 0x3e, 0x9a, 0xd6, 0x17, 0x0b, 0xd0, 0x3f, 0x8e,
0xb7, 0xdf, 0x8b, 0xdc, 0x17, 0xbe, 0x80, 0x45, 0x9f, 0x9f, 0xb0, 0xf2, 0xf8, 0x2d, 0xbe, 0xe0,
0xf8, 0x6d, 0xf8, 0x31, 0xb6, 0xed, 0xdb, 0xd0, 0xb4, 0xc7, 0x17, 0xd4, 0x0f, 0x1d, 0xb4, 0x06,
0x22, 0xb3, 0x2f, 0xbc, 0xd5, 0x35, 0x38, 0x72, 0xd5, 0xef, 0xc0, 0x92, 0x08, 0xa7, 0xa2, 0x30,
0x45, 0xc4, 0xd2, 0x08, 0xcc, 0x10, 0x8d, 0x7f, 0x2c, 0x1d, 0xf6, 0xe3, 0x4b, 0xf5, 0xc5, 0xa3,
0xa2, 0xf7, 0x30, 0x9f, 0x76, 0xd0, 0x10, 0xbb, 0x42, 0x18, 0x19, 0x05, 0x71, 0xe5, 0x40, 0x61,
0x62, 0x8c, 0x0f, 0x6b, 0xf1, 0x55, 0x86, 0xd5, 0xf8, 0xd7, 0x39, 0x28, 0xef, 0x7b, 0xb3, 0x7d,
0x87, 0x5f, 0xfb, 0xc2, 0xe5, 0xa8, 0x6c, 0xe0, 0x0b, 0xec, 0x13, 0x5d, 0x13, 0x5f, 0x70, 0x1d,
0x3c, 0x93, 0x67, 0x6d, 0xc4, 0x79, 0xd6, 0xef, 0xc2, 0x2d, 0x74, 0x31, 0xf0, 0xbd, 0x99, 0xe7,
0x33, 0xba, 0x63, 0x4f, 0x38, 0xef, 0xea, 0xb9, 0xe1, 0xb9, 0x3c, 0x08, 0x6e, 0x9e, 0x52, 0x7a,
0xa4, 0x61, 0x1c, 0x2a, 0x04, 0x0c, 0x05, 0x31, 0x09, 0x2f, 0x2c, 0xae, 0x03, 0x11, 0xcc, 0x35,
0x3f, 0x1e, 0x96, 0x58, 0x42, 0x07, 0xe1, 0xc8, 0x5e, 0x1b, 0x9f, 0x41, 0x55, 0xa9, 0xd3, 0xc8,
0xbb, 0x50, 0x3d, 0xf7, 0x66, 0x42, 0xe7, 0x96, 0x8b, 0x5d, 0x99, 0x17, 0xbd, 0x36, 0x2b, 0xe7,
0xfc, 0x47, 0x60, 0xfc, 0xdf, 0x32, 0x94, 0xbb, 0xee, 0x85, 0xe7, 0x8c, 0xd0, 0x95, 0x7f, 0x4a,
0xa7, 0x9e, 0x8c, 0x10, 0xc5, 0x7e, 0xa3, 0xa4, 0x1e, 0x05, 0x15, 0x2d, 0x08, 0x49, 0x5d, 0x85,
0x13, 0x5d, 0x83, 0x05, 0x5f, 0x8f, 0x0a, 0x5a, 0xf2, 0xf1, 0xa2, 0x94, 0x3a, 0xfc, 0x4b, 0x5a,
0xa4, 0x2f, 0x56, 0x16, 0xf7, 0x9e, 0xc6, 0x21, 0xe3, 0xe1, 0x1c, 0xaa, 0x08, 0xc1, 0x01, 0x7b,
0x0d, 0xca, 0x42, 0xb3, 0xce, 0xef, 0xcb, 0x72, 0x7b, 0x84, 0x00, 0xe1, 0x6a, 0xf0, 0x29, 0x77,
0x11, 0x51, 0x5c, 0x79, 0xc1, 0xac, 0x4b, 0xe0, 0xae, 0xcd, 0xfd, 0xf3, 0x39, 0x3e, 0x47, 0xe1,
0xa7, 0x18, 0x70, 0x10, 0x22, 0x64, 0xc4, 0xdf, 0xad, 0x66, 0xc6, 0xdf, 0xc5, 0xfb, 0x1c, 0xea,
0xc8, 0xe0, 0x5d, 0x04, 0x1e, 0x52, 0x55, 0x83, 0xcb, 0x70, 0xd7, 0x42, 0x6b, 0xc5, 0x23, 0x9d,
0x48, 0xad, 0xd5, 0x9b, 0xd0, 0x38, 0xb5, 0x27, 0x93, 0x13, 0x7b, 0xf4, 0x8c, 0xeb, 0x4e, 0xea,
0x5c, 0xbf, 0x2c, 0x81, 0xa8, 0x3c, 0xb9, 0x03, 0x35, 0x6d, 0x96, 0xd1, 0x6d, 0xbd, 0x68, 0x42,
0x34, 0xbf, 0x49, 0x1d, 0xea, 0xe2, 0x2b, 0xe8, 0x50, 0x35, 0xf7, 0xfd, 0xa5, 0xb8, 0xfb, 0xfe,
0x2d, 0x3c, 0x1a, 0x84, 0xfe, 0xa4, 0xc9, 0xe3, 0x77, 0xda, 0x63, 0xae, 0x3d, 0x41, 0x55, 0x21,
0x1f, 0x3c, 0x9e, 0xbe, 0x2c, 0xee, 0x3f, 0x20, 0x8c, 0xa3, 0xdc, 0xe6, 0x86, 0x80, 0x99, 0xed,
0x8c, 0xf1, 0x76, 0x9a, 0xb0, 0x19, 0xd9, 0xd3, 0xf0, 0xc8, 0x76, 0xd0, 0x1d, 0x54, 0x26, 0xe3,
0x51, 0xbf, 0xc2, 0xc7, 0x5f, 0x24, 0x0f, 0x78, 0x1c, 0x1f, 0x85, 0x31, 0x55, 0xa1, 0x4a, 0xcc,
0x9a, 0x40, 0xc1, 0x75, 0xf0, 0x21, 0x7a, 0x11, 0x86, 0x14, 0x83, 0x91, 0x2c, 0x2a, 0x93, 0x99,
0x58, 0xa5, 0xf2, 0x3f, 0x37, 0xbe, 0x73, 0x4c, 0xc6, 0xa9, 0x72, 0x1f, 0x80, 0xf5, 0xd8, 0x59,
0x22, 0x50, 0xd1, 0x07, 0x80, 0x23, 0x90, 0xcf, 0xb4, 0x33, 0xa4, 0x85, 0xc8, 0xaf, 0x25, 0xca,
0xbf, 0xee, 0x3e, 0xf0, 0x6d, 0x00, 0x27, 0x60, 0xc7, 0x65, 0x40, 0xdd, 0x31, 0xc6, 0x14, 0xa9,
0x98, 0x55, 0x27, 0x78, 0xc2, 0x01, 0x29, 0x45, 0xd9, 0x66, 0x3a, 0x44, 0xf0, 0x37, 0x7a, 0x04,
0xb5, 0xa1, 0xae, 0x8f, 0x04, 0xa9, 0x40, 0xb1, 0x7f, 0xd4, 0xe9, 0x35, 0x6f, 0x90, 0x1a, 0x94,
0x07, 0x9d, 0xe1, 0xf0, 0x00, 0x9d, 0x0d, 0xea, 0x50, 0x51, 0x41, 0x05, 0xf2, 0xec, 0xab, 0xbd,
0xb3, 0xd3, 0x39, 0x1a, 0x76, 0x76, 0x9b, 0x85, 0xef, 0x17, 0x2b, 0xf9, 0x66, 0xc1, 0xf8, 0xdf,
0x05, 0xa8, 0x69, 0x03, 0xf5, 0x62, 0x7a, 0x1d, 0x0f, 0x5f, 0x95, 0x4f, 0x86, 0xaf, 0xd2, 0x0d,
0x45, 0x22, 0xc4, 0x97, 0x34, 0x14, 0xbd, 0x09, 0x0d, 0x11, 0x5d, 0x54, 0x73, 0x19, 0x29, 0x99,
0x75, 0x0e, 0x14, 0xd4, 0x1c, 0x43, 0x94, 0x20, 0x12, 0x5e, 0xfe, 0x2e, 0x89, 0xf5, 0x83, 0x20,
0xbc, 0xfe, 0x8d, 0x77, 0xf7, 0x03, 0x6f, 0x72, 0x41, 0x39, 0x06, 0xe7, 0x80, 0x6b, 0x02, 0x36,
0x14, 0xe1, 0x5f, 0x04, 0xc9, 0xd4, 0x62, 0x64, 0x94, 0xcc, 0x3a, 0x07, 0x8a, 0x8a, 0xde, 0x97,
0x6b, 0x8c, 0x3b, 0xd0, 0x6d, 0xa4, 0x17, 0x4c, 0x6c, 0x7d, 0x1d, 0xa4, 0x54, 0xb3, 0x55, 0x5c,
0x3b, 0xdf, 0x4a, 0xe7, 0x7b, 0xb9, 0x8a, 0x96, 0xbc, 0x0b, 0x64, 0x3a, 0x9b, 0x59, 0x19, 0x4a,
0xd3, 0xa2, 0xb9, 0x34, 0x9d, 0xcd, 0x86, 0x9a, 0xbe, 0x8f, 0xbc, 0x06, 0x05, 0x7b, 0x3a, 0x43,
0xd2, 0x12, 0x29, 0x17, 0xdb, 0x87, 0x47, 0x26, 0x03, 0x7f, 0x03, 0xda, 0xde, 0xdf, 0xcc, 0x41,
0xa1, 0x7d, 0x78, 0xf4, 0x13, 0x52, 0xc9, 0x62, 0xe4, 0xd3, 0xe8, 0x78, 0xc0, 0xdf, 0xfc, 0x36,
0xa5, 0x38, 0x51, 0xf8, 0x5d, 0x03, 0xf5, 0x6d, 0xfc, 0x8d, 0x1c, 0x90, 0x36, 0xa3, 0x48, 0x38,
0xa0, 0x4a, 0x50, 0x8e, 0xce, 0x99, 0x9c, 0x7e, 0xce, 0x64, 0x90, 0xf3, 0x7c, 0x26, 0x39, 0x7f,
0x19, 0xe1, 0x8b, 0x6d, 0xdd, 0xe5, 0xd4, 0xd6, 0x35, 0xf6, 0xa0, 0x76, 0xa4, 0x45, 0xad, 0xbe,
0xcb, 0x4e, 0x45, 0x19, 0xaf, 0x9a, 0x9f, 0x97, 0x5c, 0x29, 0xec, 0x8b, 0x30, 0xd5, 0x5a, 0x83,
0xf3, 0x5a, 0x83, 0x8d, 0xbf, 0x97, 0xe3, 0x11, 0x17, 0x55, 0xff, 0xa2, 0x40, 0xd9, 0xd2, 0xe0,
0x1b, 0xc5, 0xe6, 0xa9, 0x49, 0x93, 0xae, 0x08, 0xab, 0x83, 0xad, 0xb7, 0xbc, 0xd3, 0xd3, 0x80,
0x4a, 0xbf, 0xb9, 0x1a, 0xc2, 0xfa, 0x08, 0x92, 0xd2, 0x13, 0x13, 0xd1, 0x1c, 0x5e, 0x7e, 0x20,
0x9c, 0xe5, 0x98, 0xf4, 0x74, 0x68, 0x5f, 0x8a, 0x5a, 0x03, 0x36, 0x03, 0xc2, 0xea, 0x24, 0x63,
0x53, 0xa8, 0x6f, 0xe3, 0x6f, 0x8b, 0xf0, 0x41, 0xc9, 0x29, 0xb8, 0x0f, 0x15, 0x55, 0x6a, 0x9c,
0xab, 0x90, 0x98, 0x2a, 0x9d, 0xf1, 0x2e, 0xa8, 0xcd, 0x8a, 0xb5, 0x98, 0x53, 0x0b, 0xb4, 0x1c,
0x76, 0xb5, 0x56, 0xbf, 0x07, 0xe4, 0xd4, 0xf1, 0x93, 0xc8, 0x9c, 0x7a, 0x34, 0x31, 0x45, 0xc3,
0x36, 0x8e, 0x61, 0x45, 0x92, 0x3d, 0x4d, 0xa4, 0x8b, 0xcf, 0x6f, 0xee, 0x25, 0x07, 0x5b, 0x3e,
0x75, 0xb0, 0x19, 0xbf, 0x51, 0x82, 0xb2, 0x0c, 0x12, 0x9f, 0x15, 0xb5, 0xbc, 0x1a, 0x8f, 0x5a,
0xde, 0x8a, 0x45, 0x32, 0xc5, 0xa9, 0x17, 0x3c, 0xce, 0x3b, 0x49, 0x36, 0x45, 0xb3, 0x80, 0xc5,
0x58, 0x15, 0x61, 0x01, 0x2b, 0xc5, 0x2d, 0x60, 0x59, 0x91, 0xdc, 0x39, 0xbb, 0x9d, 0x8a, 0xe4,
0x7e, 0x0b, 0x38, 0xef, 0xa4, 0x39, 0x0c, 0x57, 0x10, 0x20, 0xe2, 0xab, 0x68, 0xac, 0x56, 0x25,
0xc9, 0x6a, 0xbd, 0x32, 0x1b, 0xf4, 0x31, 0x2c, 0xf0, 0x50, 0x64, 0x22, 0xd6, 0x86, 0x3c, 0x2c,
0xc5, 0x58, 0xc9, 0xff, 0xfc, 0x1e, 0x9a, 0x29, 0x70, 0xf5, 0x70, 0xbd, 0xb5, 0x58, 0xb8, 0x5e,
0xdd, 0x32, 0x57, 0x8f, 0x5b, 0xe6, 0xee, 0x41, 0x53, 0x0d, 0x1c, 0xaa, 0x94, 0xdd, 0x40, 0x5c,
0xab, 0x5f, 0x94, 0x70, 0x46, 0xde, 0x7b, 0x41, 0x74, 0xd8, 0x2f, 0xc6, 0x0e, 0x7b, 0x46, 0x7c,
0xdb, 0x61, 0x48, 0xa7, 0xb3, 0x50, 0x1e, 0xf6, 0x5a, 0xf0, 0x7c, 0x3e, 0xf3, 0xfc, 0x9e, 0x9e,
0x9c, 0x5e, 0xbe, 0x3a, 0xb6, 0x61, 0xf1, 0xd4, 0x76, 0x26, 0x73, 0x9f, 0x5a, 0x3e, 0xb5, 0x03,
0xcf, 0x45, 0xfa, 0x10, 0xf1, 0x1d, 0xa2, 0x8b, 0x7b, 0x1c, 0xc7, 0x44, 0x14, 0xb3, 0x71, 0xaa,
0x7f, 0xe2, 0xad, 0x58, 0x7d, 0x24, 0xd8, 0x19, 0x2c, 0x22, 0x6e, 0x70, 0xff, 0xbf, 0x6e, 0xcf,
0xda, 0x3b, 0xe8, 0x3e, 0xde, 0x1f, 0x36, 0x73, 0xec, 0x73, 0x70, 0xbc, 0xb3, 0xd3, 0xe9, 0xec,
0xe2, 0x99, 0x0c, 0xb0, 0xb0, 0xd7, 0xee, 0x1e, 0x88, 0x13, 0xb9, 0xd8, 0x2c, 0x19, 0x7f, 0x94,
0x87, 0x9a, 0xd6, 0x1b, 0x8c, 0xa5, 0xc3, 0x7f, 0x32, 0xfa, 0x5b, 0x16, 0xb1, 0x74, 0x38, 0xa4,
0x3b, 0x26, 0x8f, 0xd4, 0x1c, 0xf1, 0x10, 0x40, 0xb7, 0xd3, 0x03, 0xb2, 0x25, 0x4f, 0x34, 0x6d,
0x92, 0x54, 0x14, 0xfd, 0xfc, 0xb5, 0x51, 0xf4, 0xc9, 0xdb, 0xb0, 0x24, 0x6b, 0x96, 0x73, 0x22,
0x8c, 0x37, 0x02, 0x2c, 0xa6, 0xe4, 0x6d, 0x11, 0x8e, 0x48, 0x1c, 0xcb, 0x0c, 0xaf, 0x28, 0xfd,
0xe4, 0xd5, 0xc9, 0x8c, 0x53, 0x57, 0x16, 0x03, 0x27, 0x3c, 0x40, 0x14, 0x83, 0x23, 0x86, 0x53,
0x26, 0xc7, 0xce, 0x88, 0x85, 0xc4, 0x19, 0xf1, 0x09, 0x40, 0xd4, 0x9f, 0xf8, 0xe8, 0xde, 0x88,
0x8f, 0x6e, 0x4e, 0x1b, 0xdd, 0xbc, 0xf1, 0x8f, 0x04, 0x65, 0x13, 0x53, 0xa5, 0x54, 0xb9, 0xef,
0x83, 0x54, 0x2e, 0x5b, 0x78, 0xaf, 0x66, 0x36, 0xa1, 0xa1, 0x0c, 0x1a, 0xb0, 0x2c, 0x52, 0xba,
0x2a, 0x21, 0x45, 0x89, 0xf3, 0x69, 0x4a, 0xfc, 0x06, 0xd4, 0x31, 0xbe, 0xa5, 0xa8, 0x48, 0x06,
0x98, 0x9e, 0xda, 0x97, 0xb2, 0xee, 0x18, 0x09, 0x2e, 0x26, 0x48, 0xf0, 0xdf, 0xc9, 0xf1, 0x60,
0x68, 0x51, 0x43, 0x23, 0x1a, 0xac, 0xca, 0x8c, 0xd3, 0x60, 0x81, 0x6a, 0xaa, 0xf4, 0x6b, 0xe8,
0x6a, 0x3e, 0x9b, 0xae, 0x66, 0x53, 0xec, 0x42, 0x26, 0xc5, 0x36, 0x2e, 0xa1, 0xb5, 0x4b, 0xd9,
0x50, 0xb4, 0x27, 0x93, 0xe4, 0x58, 0x3e, 0x80, 0x55, 0x36, 0x85, 0xe8, 0xfe, 0xc2, 0x53, 0xf4,
0x13, 0x8d, 0xf0, 0x34, 0x99, 0x09, 0x0f, 0xb6, 0xfb, 0xb0, 0x2c, 0x72, 0xe0, 0xa6, 0xd5, 0x23,
0xcf, 0x2d, 0xf1, 0x04, 0x74, 0xdb, 0x65, 0xb8, 0xc6, 0x2d, 0xb8, 0x99, 0x51, 0xb3, 0xd0, 0xf9,
0xfd, 0x66, 0x0e, 0xd6, 0xda, 0x3c, 0xc2, 0xd2, 0x37, 0x16, 0x33, 0xe0, 0x73, 0xb8, 0xa9, 0xae,
0xe0, 0x68, 0x57, 0x87, 0xf5, 0x46, 0xca, 0xdb, 0x3b, 0xda, 0xc5, 0x33, 0x6c, 0x6b, 0x0b, 0xd6,
0x93, 0xad, 0x11, 0x0d, 0xdd, 0x83, 0xe5, 0x5d, 0x7a, 0x32, 0x3f, 0x3b, 0xa0, 0x17, 0x51, 0x1b,
0x09, 0x14, 0x83, 0x73, 0xef, 0xb9, 0x18, 0x28, 0xfc, 0x8d, 0x3e, 0xfa, 0x0c, 0xc7, 0x0a, 0x66,
0x74, 0x24, 0x6d, 0x46, 0x08, 0x19, 0xcc, 0xe8, 0xc8, 0x78, 0x04, 0x44, 0x2f, 0x47, 0xac, 0x11,
0x26, 0x03, 0xcf, 0x4f, 0xac, 0xe0, 0x2a, 0x08, 0xe9, 0x54, 0x5e, 0x9f, 0x87, 0x60, 0x7e, 0x32,
0xe0, 0x10, 0xe3, 0x1d, 0xa8, 0x1f, 0xd9, 0x57, 0x26, 0xfd, 0xa1, 0xb8, 0x81, 0xbe, 0x01, 0xe5,
0x99, 0x7d, 0xc5, 0x0e, 0x02, 0x65, 0x3e, 0xc6, 0x64, 0xe3, 0xf7, 0x8a, 0xb0, 0xc0, 0x31, 0xc9,
0x5d, 0xfe, 0xc0, 0x8e, 0xe3, 0x22, 0x21, 0x96, 0x47, 0xa2, 0x06, 0x4a, 0x9d, 0x9a, 0xf9, 0xf4,
0xa9, 0x29, 0x74, 0xdd, 0x32, 0x7c, 0xa7, 0x34, 0xf4, 0xb9, 0xf3, 0xa9, 0x8c, 0xd9, 0x19, 0x8f,
0x27, 0x54, 0x8c, 0x9e, 0x6c, 0xe2, 0xb1, 0x54, 0xe2, 0xfe, 0x21, 0x91, 0xa4, 0xcd, 0x5b, 0x27,
0x99, 0x01, 0x71, 0x60, 0xea, 0xa0, 0x4c, 0x71, 0xbe, 0x2c, 0xc3, 0x33, 0xc4, 0xc5, 0xf9, 0x94,
0xd8, 0x5e, 0x79, 0xb9, 0xd8, 0xce, 0x95, 0xe0, 0x2f, 0x10, 0xdb, 0xe1, 0x15, 0xc4, 0xf6, 0x57,
0x70, 0xb5, 0xb8, 0x09, 0x15, 0xe4, 0xf0, 0xb4, 0xf3, 0x93, 0x71, 0x76, 0xec, 0xfc, 0xfc, 0x54,
0x13, 0x6c, 0xb9, 0x63, 0x98, 0x76, 0x80, 0x99, 0xf4, 0x87, 0x3f, 0x1d, 0xc5, 0xe8, 0x53, 0x28,
0x0b, 0x28, 0x5b, 0xd0, 0xae, 0x3d, 0x95, 0x41, 0xaa, 0xf1, 0x37, 0x1b, 0x36, 0x0c, 0xdb, 0xfa,
0xc3, 0xb9, 0xe3, 0xd3, 0xb1, 0x0c, 0x1e, 0xe9, 0x20, 0xf5, 0x60, 0x10, 0xd6, 0x41, 0x26, 0x64,
0xbb, 0xf2, 0x6d, 0x8d, 0x8a, 0x59, 0x76, 0x82, 0x27, 0xec, 0xd3, 0x20, 0xd0, 0xc4, 0x27, 0x01,
0x66, 0x9e, 0x2f, 0xd9, 0x13, 0xe3, 0xf7, 0x73, 0xd0, 0x14, 0xbb, 0x4b, 0xa5, 0xe9, 0x02, 0x6c,
0xe9, 0x3a, 0x3f, 0xa6, 0x17, 0x87, 0x82, 0x34, 0xa0, 0x81, 0xaa, 0x3d, 0xc5, 0xab, 0x70, 0xd5,
0x64, 0x8d, 0x01, 0xf7, 0x04, 0xbf, 0xf2, 0x3a, 0xd4, 0xe4, 0x0d, 0xa2, 0xa9, 0x33, 0x91, 0xaf,
0xb3, 0xf1, 0x2b, 0x44, 0x87, 0xce, 0x44, 0xb2, 0x3a, 0xbe, 0x2d, 0x42, 0x86, 0xe4, 0x90, 0xd5,
0x31, 0xed, 0x90, 0x1a, 0x7f, 0x98, 0x83, 0x65, 0xad, 0x2b, 0x62, 0xdf, 0x7e, 0x07, 0xea, 0xea,
0xcd, 0x13, 0xaa, 0x78, 0xec, 0x8d, 0x38, 0x8d, 0x8a, 0xb2, 0xd5, 0x46, 0x0a, 0x12, 0xb0, 0xc6,
0x8c, 0xed, 0x2b, 0x7e, 0xcd, 0x65, 0x3e, 0x95, 0x72, 0xf9, 0xd8, 0xbe, 0xda, 0xa3, 0x74, 0x30,
0x9f, 0x92, 0xbb, 0x50, 0x7f, 0x4e, 0xe9, 0x33, 0x85, 0xc0, 0x09, 0x3b, 0x30, 0x98, 0xc0, 0x30,
0xa0, 0x31, 0xf5, 0xdc, 0xf0, 0x5c, 0xa1, 0x08, 0xf9, 0x02, 0x81, 0x1c, 0xc7, 0xf8, 0xb7, 0x79,
0x58, 0xe1, 0x0a, 0x64, 0x61, 0x85, 0x10, 0xa4, 0xab, 0x05, 0x0b, 0xdc, 0x20, 0xc0, 0x89, 0xd7,
0xfe, 0x0d, 0x53, 0x7c, 0x93, 0x8f, 0x5f, 0x51, 0xe9, 0x2d, 0xa3, 0x8d, 0x5c, 0x33, 0xfc, 0x85,
0xf4, 0xf0, 0x5f, 0x3f, 0xbc, 0x59, 0x3e, 0x09, 0xa5, 0x2c, 0x9f, 0x84, 0x57, 0xf1, 0x04, 0x48,
0xc5, 0xbb, 0x28, 0xa7, 0xe3, 0x4e, 0x3f, 0x82, 0x8d, 0x18, 0x0e, 0x52, 0x6b, 0xe7, 0xd4, 0x51,
0x0f, 0x26, 0xac, 0x6a, 0xd8, 0x03, 0x99, 0xb6, 0x5d, 0x86, 0x52, 0x30, 0xf2, 0x66, 0xe8, 0x5b,
0x1f, 0x1f, 0x55, 0x71, 0x4c, 0xfc, 0x4e, 0x0e, 0x5a, 0x7b, 0x51, 0x00, 0x6f, 0x27, 0x08, 0x3d,
0x5f, 0xbd, 0x45, 0x71, 0x1b, 0x80, 0xbf, 0x14, 0x87, 0x6a, 0x10, 0x11, 0x79, 0x0d, 0x21, 0xa8,
0x04, 0xb9, 0x09, 0x15, 0xea, 0x8e, 0x79, 0x22, 0x5f, 0x0d, 0x65, 0xea, 0x8e, 0xa5, 0x0a, 0x25,
0x75, 0xc8, 0x37, 0xe2, 0xec, 0x8b, 0x88, 0x21, 0xc4, 0x46, 0x87, 0x5e, 0x20, 0xb3, 0x51, 0x54,
0x31, 0x84, 0x0e, 0xed, 0x4b, 0xbc, 0x22, 0x11, 0x18, 0xff, 0x24, 0x0f, 0x4b, 0x51, 0xfb, 0x78,
0x14, 0xb5, 0xbb, 0xa9, 0x78, 0x70, 0xc2, 0x9d, 0x4a, 0xd1, 0xf0, 0xbb, 0x62, 0x49, 0x38, 0x4c,
0x5a, 0xd3, 0x54, 0xeb, 0x15, 0xbe, 0x41, 0xbb, 0x2e, 0x31, 0xa0, 0x26, 0x31, 0xbc, 0x79, 0xa8,
0xc5, 0xcb, 0xae, 0x72, 0x94, 0xfe, 0x3c, 0x64, 0xe2, 0xb5, 0x3d, 0x65, 0xdc, 0x8a, 0x10, 0x70,
0x4b, 0xf6, 0x34, 0xec, 0xe2, 0x93, 0x84, 0x0c, 0xcc, 0xb2, 0xf1, 0xc9, 0x64, 0x58, 0x0c, 0xbf,
0xc9, 0xa5, 0x2d, 0x3e, 0x7b, 0x28, 0x69, 0xe9, 0xa2, 0x08, 0x7f, 0x08, 0x49, 0x89, 0x22, 0xaf,
0x43, 0x8d, 0x17, 0x1e, 0x85, 0x38, 0xc1, 0xe0, 0x95, 0x61, 0xd7, 0xc5, 0x74, 0xa1, 0xe6, 0xf4,
0xe6, 0x31, 0xcd, 0x0d, 0xf0, 0xaa, 0xe4, 0xeb, 0x71, 0xaa, 0xc7, 0x96, 0xb2, 0x61, 0xd6, 0x14,
0xac, 0x17, 0x30, 0x6e, 0xe5, 0x66, 0xc6, 0xec, 0x0a, 0x62, 0xb0, 0x03, 0x5a, 0xb4, 0x77, 0x39,
0x09, 0x9c, 0x22, 0xac, 0x4b, 0xea, 0x1b, 0x1f, 0x7a, 0xb3, 0x79, 0x1a, 0x07, 0x44, 0x52, 0x38,
0x9f, 0xe8, 0x58, 0x2c, 0x1e, 0xe4, 0xe9, 0xf8, 0x6c, 0x73, 0x01, 0xf8, 0x08, 0x36, 0x3b, 0x97,
0x8c, 0xb0, 0xa8, 0xcb, 0x02, 0xa3, 0x67, 0x73, 0x69, 0x5e, 0x4d, 0x58, 0x59, 0x72, 0xaf, 0x64,
0x65, 0x19, 0xf3, 0x08, 0x18, 0xaa, 0xac, 0x1f, 0xa7, 0x10, 0xae, 0x5f, 0xb2, 0x5d, 0xeb, 0x04,
0x8b, 0x90, 0x01, 0x77, 0x18, 0x88, 0x17, 0x6a, 0x04, 0xb0, 0x74, 0x38, 0x9f, 0x84, 0xce, 0x8e,
0x02, 0x91, 0x8f, 0x45, 0x1e, 0xac, 0x47, 0x8e, 0x5a, 0x66, 0x45, 0xa0, 0x2a, 0xc2, 0xc1, 0x9a,
0xb2, 0x82, 0xac, 0x74, 0x7d, 0x4b, 0xd3, 0x78, 0x0d, 0xc6, 0x4d, 0xd8, 0x88, 0xbe, 0xf8, 0xb0,
0xc9, 0x13, 0xe9, 0xef, 0xe6, 0xf8, 0xb5, 0x2d, 0x9e, 0x36, 0x70, 0xed, 0x59, 0x70, 0xee, 0x85,
0xa4, 0x03, 0x2b, 0x81, 0xe3, 0x9e, 0x4d, 0xa8, 0x5e, 0x7c, 0x20, 0x06, 0x61, 0x2d, 0xde, 0x36,
0x9e, 0x35, 0x30, 0x97, 0x79, 0x8e, 0xa8, 0xb4, 0x80, 0x6c, 0x5f, 0xd7, 0xc8, 0x68, 0x59, 0x24,
0x46, 0x23, 0xdd, 0xf8, 0x2e, 0x2c, 0xc6, 0x2b, 0x22, 0x9f, 0x8a, 0xc0, 0x31, 0x51, 0xab, 0x0a,
0x89, 0xb0, 0x19, 0xd1, 0x82, 0xa8, 0x45, 0x63, 0x1f, 0x18, 0x7f, 0x3d, 0x07, 0x2d, 0x93, 0xb2,
0x95, 0xab, 0xb5, 0x52, 0xae, 0x99, 0xef, 0xa4, 0x4a, 0xbd, 0xbe, 0xaf, 0x32, 0x1e, 0x8d, 0x6c,
0xd1, 0x7b, 0xd7, 0x4e, 0xc6, 0xfe, 0x8d, 0x54, 0x8f, 0xb6, 0x2b, 0xb0, 0xc0, 0x51, 0x8c, 0x0d,
0x58, 0x13, 0xed, 0x91, 0x6d, 0x89, 0xfc, 0x01, 0x62, 0x35, 0xc6, 0xfc, 0x01, 0x36, 0xa1, 0xc5,
0xe3, 0x3b, 0xe8, 0x9d, 0x10, 0x19, 0x77, 0x81, 0x1c, 0xda, 0x23, 0xdb, 0xf7, 0x3c, 0xf7, 0x88,
0xfa, 0xe2, 0x1a, 0x00, 0x32, 0xa2, 0x68, 0x2a, 0x97, 0x1c, 0x33, 0xff, 0x92, 0x0f, 0x09, 0x78,
0xae, 0x74, 0x30, 0xe4, 0x5f, 0x86, 0x0f, 0x2b, 0xdb, 0xf6, 0x33, 0x2a, 0x4b, 0x92, 0x43, 0xf4,
0x05, 0xd4, 0x66, 0xaa, 0x50, 0x39, 0xee, 0x32, 0x26, 0x57, 0xba, 0x5a, 0x53, 0xc7, 0x66, 0x54,
0x0a, 0x15, 0xb6, 0x18, 0xe5, 0x66, 0x2c, 0xcf, 0x7c, 0x06, 0x7a, 0x42, 0xaf, 0xba, 0x63, 0xe3,
0x21, 0xac, 0xc6, 0xeb, 0x14, 0xa4, 0x65, 0x13, 0x2a, 0x53, 0x01, 0x13, 0xad, 0x57, 0xdf, 0x4c,
0x66, 0x61, 0x72, 0xa7, 0xcc, 0xd3, 0xdd, 0x55, 0xa1, 0x1a, 0xbe, 0x80, 0x8d, 0x54, 0x8a, 0x28,
0xf0, 0x2e, 0xd4, 0xb5, 0x86, 0xf0, 0x6e, 0x14, 0x4d, 0x50, 0x2d, 0x09, 0x8c, 0xcf, 0x61, 0x83,
0x8b, 0x6d, 0x51, 0x76, 0x39, 0x04, 0x89, 0x5e, 0xe4, 0x92, 0xbd, 0xf8, 0x58, 0xca, 0x9a, 0x7a,
0xd6, 0x28, 0x26, 0xe6, 0x18, 0xd3, 0xa4, 0x8f, 0x98, 0xfc, 0x34, 0x8e, 0x61, 0x3d, 0x3d, 0x7c,
0xac, 0xfd, 0x7f, 0xa1, 0x21, 0x97, 0xc3, 0x13, 0x25, 0xab, 0xe1, 0xf9, 0xaf, 0x39, 0x3e, 0x3e,
0xb1, 0x24, 0xd1, 0xcc, 0x31, 0x90, 0x29, 0x0d, 0xcf, 0xbd, 0xb1, 0x95, 0xae, 0xf9, 0x91, 0x72,
0x51, 0xcb, 0xcc, 0xbb, 0x75, 0x88, 0x19, 0xb5, 0x14, 0x71, 0x83, 0x63, 0x9a, 0x84, 0x6f, 0x8e,
0x60, 0x3d, 0x1b, 0x39, 0xc3, 0xb1, 0xeb, 0xa3, 0x38, 0x3f, 0x7f, 0xfb, 0xda, 0xee, 0xb3, 0x66,
0xe9, 0xec, 0xfd, 0xef, 0x55, 0xa0, 0x2c, 0x54, 0x35, 0x64, 0x0b, 0x8a, 0x23, 0xe9, 0x24, 0x1c,
0xc5, 0x45, 0x15, 0xa9, 0xf2, 0xff, 0x0e, 0xba, 0x0a, 0x33, 0x3c, 0xf2, 0x05, 0x2c, 0xc6, 0xfd,
0x64, 0x12, 0xf1, 0x8b, 0xe2, 0x0e, 0x2e, 0x8d, 0x51, 0xc2, 0x89, 0xa0, 0x1a, 0xf1, 0x60, 0x9c,
0x35, 0xad, 0x9c, 0x6b, 0x4c, 0x9a, 0xe7, 0x32, 0xb1, 0x2e, 0x38, 0xb7, 0xad, 0x87, 0x8f, 0x3e,
0x11, 0x46, 0x85, 0x1a, 0x02, 0x07, 0xe7, 0xf6, 0xc3, 0x47, 0x9f, 0x24, 0x05, 0x36, 0x11, 0xbe,
0x48, 0x13, 0xd8, 0x56, 0xa1, 0xc4, 0x5f, 0x5b, 0xe0, 0xde, 0x9e, 0xfc, 0x43, 0xaa, 0x33, 0xe6,
0x3e, 0xb5, 0xc4, 0x65, 0x21, 0x7e, 0x8a, 0xf2, 0x37, 0xf6, 0x88, 0x48, 0x1b, 0x60, 0x12, 0x57,
0x27, 0xae, 0xc3, 0xc2, 0x79, 0xf4, 0x7c, 0x46, 0xc3, 0x14, 0x5f, 0xc6, 0x9f, 0x96, 0xa0, 0xa6,
0x0d, 0x0a, 0xa9, 0x43, 0xc5, 0xec, 0x0c, 0x3a, 0xe6, 0x97, 0x9d, 0xdd, 0xe6, 0x0d, 0x72, 0x0f,
0xde, 0xea, 0xf6, 0x76, 0xfa, 0xa6, 0xd9, 0xd9, 0x19, 0x5a, 0x7d, 0xd3, 0x92, 0xe1, 0x7a, 0x8f,
0xda, 0x4f, 0x0f, 0x3b, 0xbd, 0xa1, 0xb5, 0xdb, 0x19, 0xb6, 0xbb, 0x07, 0x83, 0x66, 0x8e, 0xbc,
0x06, 0xad, 0x08, 0x53, 0x26, 0xb7, 0x0f, 0xfb, 0xc7, 0xbd, 0x61, 0x33, 0x4f, 0xee, 0xc0, 0xad,
0xbd, 0x6e, 0xaf, 0x7d, 0x60, 0x45, 0x38, 0x3b, 0x07, 0xc3, 0x2f, 0xad, 0xce, 0xcf, 0x1d, 0x75,
0xcd, 0xa7, 0xcd, 0x42, 0x16, 0xc2, 0xfe, 0xf0, 0x60, 0x47, 0x96, 0x50, 0x24, 0x37, 0x61, 0x8d,
0x23, 0xf0, 0x2c, 0xd6, 0xb0, 0xdf, 0xb7, 0x06, 0xfd, 0x7e, 0xaf, 0x59, 0x22, 0xcb, 0xd0, 0xe8,
0xf6, 0xbe, 0x6c, 0x1f, 0x74, 0x77, 0x2d, 0xb3, 0xd3, 0x3e, 0x38, 0x6c, 0x2e, 0x90, 0x15, 0x58,
0x4a, 0xe2, 0x95, 0x59, 0x11, 0x12, 0xaf, 0xdf, 0xeb, 0xf6, 0x7b, 0xd6, 0x97, 0x1d, 0x73, 0xd0,
0xed, 0xf7, 0x9a, 0x15, 0xb2, 0x0e, 0x24, 0x9e, 0xb4, 0x7f, 0xd8, 0xde, 0x69, 0x56, 0xc9, 0x1a,
0x2c, 0xc7, 0xe1, 0x4f, 0x3a, 0x4f, 0x9b, 0x40, 0x5a, 0xb0, 0xca, 0x1b, 0x66, 0x6d, 0x77, 0x0e,
0xfa, 0x5f, 0x59, 0x87, 0xdd, 0x5e, 0xf7, 0xf0, 0xf8, 0xb0, 0x59, 0xc3, 0xa0, 0xe9, 0x9d, 0x8e,
0xd5, 0xed, 0x0d, 0x8e, 0xf7, 0xf6, 0xba, 0x3b, 0xdd, 0x4e, 0x6f, 0xd8, 0xac, 0xf3, 0x9a, 0xb3,
0x3a, 0xde, 0x60, 0x19, 0xc4, 0x7d, 0x5a, 0x6b, 0xb7, 0x3b, 0x68, 0x6f, 0x1f, 0x74, 0x76, 0x9b,
0x8b, 0xe4, 0x36, 0xdc, 0x1c, 0x76, 0x0e, 0x8f, 0xfa, 0x66, 0xdb, 0x7c, 0x2a, 0xef, 0xdb, 0x5a,
0x7b, 0xed, 0xee, 0xc1, 0xb1, 0xd9, 0x69, 0x2e, 0x91, 0x37, 0xe0, 0xb6, 0xd9, 0xf9, 0xc1, 0x71,
0xd7, 0xec, 0xec, 0x5a, 0xbd, 0xfe, 0x6e, 0xc7, 0xda, 0xeb, 0xb4, 0x87, 0xc7, 0x66, 0xc7, 0x3a,
0xec, 0x0e, 0x06, 0xdd, 0xde, 0xe3, 0x66, 0x93, 0xbc, 0x05, 0x77, 0x15, 0x8a, 0x2a, 0x20, 0x81,
0xb5, 0xcc, 0xfa, 0x27, 0xa7, 0xb4, 0xd7, 0xf9, 0xb9, 0xa1, 0x75, 0xd4, 0xe9, 0x98, 0x4d, 0x42,
0x36, 0x61, 0x3d, 0xaa, 0x9e, 0x57, 0x20, 0xea, 0x5e, 0x61, 0x69, 0x47, 0x1d, 0xf3, 0xb0, 0xdd,
0x63, 0x13, 0x1c, 0x4b, 0x5b, 0x65, 0xcd, 0x8e, 0xd2, 0x92, 0xcd, 0x5e, 0x23, 0x04, 0x16, 0xb5,
0x59, 0xd9, 0x6b, 0x9b, 0xcd, 0x75, 0xb2, 0x04, 0xb5, 0xc3, 0xa3, 0x23, 0x6b, 0xd8, 0x3d, 0xec,
0xf4, 0x8f, 0x87, 0xcd, 0x8d, 0xf4, 0x2c, 0x1d, 0xb5, 0x9f, 0x1e, 0xf4, 0xdb, 0xbb, 0xcd, 0x16,
0x59, 0x83, 0x66, 0xb7, 0x37, 0xec, 0x98, 0x6c, 0x19, 0xc8, 0x52, 0xff, 0x5b, 0x99, 0xac, 0xc2,
0x92, 0xec, 0x84, 0x84, 0xfe, 0x71, 0x99, 0x6c, 0x00, 0x39, 0xee, 0x99, 0x9d, 0xf6, 0x2e, 0x1b,
0x53, 0x95, 0xf0, 0xdf, 0xcb, 0xc2, 0xbc, 0xfc, 0xfb, 0x05, 0xc5, 0x07, 0x8a, 0xbd, 0x9c, 0x7a,
0x0a, 0xab, 0xae, 0x3d, 0x61, 0xf5, 0xb2, 0x87, 0x57, 0x35, 0xe1, 0xbe, 0x90, 0x12, 0xee, 0x53,
0xda, 0xa3, 0x86, 0x2e, 0x79, 0xbc, 0x09, 0x8d, 0x29, 0x7f, 0x16, 0x4b, 0xbc, 0xab, 0x02, 0xc2,
0x59, 0x93, 0x03, 0xf9, 0xa3, 0x2a, 0xa9, 0x97, 0x47, 0x4b, 0xe9, 0x97, 0x47, 0xb3, 0x24, 0xcc,
0x85, 0x2c, 0x09, 0xf3, 0x3e, 0x2c, 0x73, 0xaa, 0xe5, 0xb8, 0xce, 0x54, 0xea, 0x6d, 0xc4, 0x3b,
0x9e, 0x48, 0xbd, 0x38, 0x5c, 0x0a, 0xb4, 0x52, 0xe8, 0x15, 0xd4, 0xa5, 0x2c, 0xe4, 0xdd, 0x98,
0xac, 0xcb, 0x89, 0x8a, 0x92, 0x75, 0x55, 0x0d, 0xf6, 0x65, 0x54, 0x43, 0x4d, 0xab, 0x81, 0xc3,
0xb1, 0x86, 0xfb, 0xb0, 0x4c, 0x2f, 0x43, 0xdf, 0xb6, 0xbc, 0x99, 0xfd, 0xc3, 0x39, 0xba, 0xc8,
0xd8, 0xa8, 0x45, 0xaa, 0x9b, 0x4b, 0x98, 0xd0, 0x47, 0xf8, 0xae, 0x1d, 0xda, 0xc6, 0x2f, 0x02,
0xa8, 0x03, 0x17, 0xdf, 0x43, 0x75, 0x3d, 0x79, 0x4f, 0xb8, 0x6e, 0xf2, 0x0f, 0x9c, 0xc7, 0xd0,
0xf3, 0xed, 0x33, 0xda, 0x95, 0x56, 0xe1, 0x08, 0x40, 0x6e, 0x41, 0xc1, 0x9b, 0x49, 0x57, 0xc6,
0xaa, 0x7c, 0x28, 0x60, 0x66, 0x32, 0xa8, 0xf1, 0x09, 0xe4, 0xfb, 0xb3, 0x6b, 0xb9, 0x28, 0x7c,
0xb4, 0x8d, 0xbf, 0xd4, 0x90, 0xc7, 0x08, 0xc5, 0xf2, 0xf3, 0xfe, 0x5f, 0x86, 0x9a, 0xf6, 0xc6,
0x1b, 0xd9, 0x80, 0x95, 0xaf, 0xba, 0xc3, 0x5e, 0x67, 0x30, 0xb0, 0x8e, 0x8e, 0xb7, 0x9f, 0x74,
0x9e, 0x5a, 0xfb, 0xed, 0xc1, 0x7e, 0xf3, 0x06, 0x23, 0x33, 0xbd, 0xce, 0x60, 0xd8, 0xd9, 0x8d,
0xc1, 0x73, 0xe4, 0x75, 0xd8, 0x3c, 0xee, 0x1d, 0x0f, 0x3a, 0xbb, 0x56, 0x56, 0xbe, 0x3c, 0xdb,
0x57, 0x22, 0x3d, 0x23, 0x7b, 0xe1, 0xfe, 0x2f, 0xc1, 0x62, 0x3c, 0x58, 0x0e, 0x01, 0x58, 0x38,
0xe8, 0x3c, 0x6e, 0xef, 0x3c, 0xe5, 0x0f, 0x41, 0x0c, 0x86, 0xed, 0x61, 0x77, 0xc7, 0x12, 0x0f,
0x3f, 0x30, 0x1a, 0x96, 0x23, 0x35, 0x28, 0xb7, 0x7b, 0x3b, 0xfb, 0x7d, 0x73, 0xd0, 0xcc, 0x93,
0xd7, 0x60, 0x43, 0x6e, 0xa1, 0x9d, 0xfe, 0xe1, 0x61, 0x77, 0x88, 0xe4, 0x7b, 0xf8, 0xf4, 0x88,
0xed, 0x98, 0xfb, 0x36, 0x54, 0xa3, 0x37, 0x2b, 0x90, 0x24, 0x76, 0x87, 0xdd, 0xf6, 0x30, 0x3a,
0x0f, 0x9a, 0x37, 0x18, 0xc5, 0x8d, 0xc0, 0xf8, 0xf0, 0x44, 0x33, 0xc7, 0xe3, 0x09, 0x48, 0x20,
0xaf, 0xbd, 0x99, 0x67, 0x64, 0x20, 0x82, 0x6e, 0xf7, 0x87, 0xac, 0x0b, 0xbf, 0x0c, 0x8b, 0xf1,
0xa7, 0x21, 0x48, 0x13, 0xea, 0xac, 0x7e, 0xad, 0x0a, 0x80, 0x05, 0xde, 0xe2, 0x66, 0x8e, 0xd3,
0xfc, 0x9d, 0xfe, 0x61, 0xb7, 0xf7, 0x18, 0x0f, 0x8a, 0x66, 0x9e, 0x81, 0xfa, 0xc7, 0xc3, 0xc7,
0x7d, 0x05, 0x2a, 0xb0, 0x1c, 0xbc, 0x3b, 0xcd, 0xe2, 0xfd, 0x1f, 0xc2, 0x72, 0xea, 0x11, 0x09,
0xd6, 0xea, 0xfe, 0xf1, 0x70, 0xa7, 0x7f, 0xa8, 0xd7, 0x53, 0x83, 0xf2, 0xce, 0x41, 0xbb, 0x7b,
0x88, 0x86, 0x9a, 0x06, 0x54, 0x8f, 0x7b, 0xf2, 0x33, 0x1f, 0x7f, 0xfe, 0xa2, 0xc0, 0xa8, 0xd7,
0x5e, 0xd7, 0x1c, 0x0c, 0xad, 0xc1, 0xb0, 0xfd, 0xb8, 0xd3, 0x2c, 0xb2, 0xbc, 0x92, 0x94, 0x95,
0xee, 0x7f, 0x0e, 0x8b, 0x71, 0xbf, 0xfb, 0xb8, 0xfd, 0x6d, 0x13, 0xd6, 0xb7, 0x3b, 0xc3, 0xaf,
0x3a, 0x9d, 0x1e, 0x4e, 0xf9, 0x4e, 0xa7, 0x37, 0x34, 0xdb, 0x07, 0xdd, 0xe1, 0xd3, 0x66, 0xee,
0xfe, 0x17, 0xd0, 0x4c, 0x3a, 0x7d, 0xc4, 0xbc, 0x64, 0x5e, 0xe4, 0x4e, 0x73, 0xff, 0x3f, 0xe4,
0x60, 0x35, 0xcb, 0x3c, 0xc8, 0x16, 0xa6, 0x20, 0x84, 0xec, 0xa4, 0x1c, 0xf4, 0x7b, 0x56, 0xaf,
0x8f, 0xe1, 0xdf, 0x37, 0x61, 0x3d, 0x91, 0x20, 0x7b, 0x91, 0x23, 0xb7, 0x60, 0x23, 0x95, 0xc9,
0x32, 0xfb, 0xc7, 0x38, 0x97, 0x2d, 0x58, 0x4d, 0x24, 0x76, 0x4c, 0xb3, 0x6f, 0x36, 0x0b, 0xe4,
0x3d, 0xb8, 0x97, 0x48, 0x49, 0xf3, 0x07, 0x92, 0x7d, 0x28, 0x92, 0x77, 0xe0, 0xcd, 0x14, 0x76,
0x74, 0x84, 0x5a, 0xdb, 0xed, 0x03, 0xd6, 0xbd, 0x66, 0xe9, 0xfe, 0x1f, 0x16, 0x01, 0xa2, 0xdb,
0xb6, 0xac, 0xfe, 0xdd, 0xf6, 0xb0, 0x7d, 0xd0, 0x67, 0x7b, 0xc6, 0xec, 0x0f, 0x59, 0xe9, 0x66,
0xe7, 0x07, 0xcd, 0x1b, 0x99, 0x29, 0xfd, 0x23, 0xd6, 0xa1, 0x0d, 0x58, 0xe1, 0xeb, 0xef, 0x80,
0x75, 0x83, 0x2d, 0x17, 0xfe, 0x92, 0x00, 0x63, 0x42, 0x8e, 0x8f, 0xf6, 0xcc, 0x7e, 0x6f, 0x68,
0x0d, 0xf6, 0x8f, 0x87, 0xbb, 0xf8, 0x30, 0xc1, 0x8e, 0xd9, 0x3d, 0xe2, 0x65, 0x16, 0x5f, 0x84,
0xc0, 0x8a, 0x2e, 0xb1, 0x0d, 0xfe, 0xb8, 0x3f, 0x18, 0x74, 0x8f, 0xac, 0x1f, 0x1c, 0x77, 0xcc,
0x6e, 0x67, 0x80, 0x19, 0x17, 0x32, 0xe0, 0x0c, 0xbf, 0xcc, 0xd6, 0xec, 0xf0, 0xe0, 0x4b, 0x71,
0xd0, 0x31, 0xd4, 0x4a, 0x1c, 0xc4, 0xb0, 0xaa, 0x6c, 0x76, 0xd8, 0xe1, 0x9c, 0x51, 0x32, 0x5c,
0x93, 0xc6, 0xf2, 0xd5, 0xd8, 0x51, 0x9a, 0xda, 0xf9, 0x98, 0xad, 0x9e, 0x9d, 0xc4, 0x72, 0x21,
0x47, 0xa2, 0xf8, 0xb7, 0xdd, 0x5d, 0x13, 0x33, 0x2c, 0xa6, 0xa0, 0x0c, 0x77, 0x89, 0x2d, 0x42,
0x76, 0x7a, 0x33, 0x94, 0xa6, 0xfc, 0x60, 0x29, 0xcb, 0xac, 0xc7, 0x5f, 0x1d, 0x1f, 0x6e, 0xf7,
0x25, 0x1b, 0xc0, 0xdb, 0x4b, 0x32, 0xe0, 0x0c, 0x7f, 0x05, 0x5f, 0x7e, 0xe0, 0xe4, 0x08, 0x11,
0x57, 0x75, 0x00, 0xc3, 0x58, 0x63, 0x44, 0x50, 0x02, 0x7e, 0xbe, 0x63, 0xf6, 0x2d, 0xc6, 0x67,
0x21, 0x8f, 0xc8, 0xf0, 0xd7, 0xaf, 0x4f, 0x66, 0xb9, 0x37, 0x1e, 0xfe, 0x8b, 0x37, 0xa0, 0xaa,
0x2e, 0xdc, 0x90, 0xef, 0x43, 0x23, 0x16, 0x64, 0x83, 0xdc, 0xca, 0x0e, 0xbd, 0x81, 0x52, 0xd4,
0xe6, 0x6b, 0x2f, 0x8a, 0xcb, 0x41, 0x0e, 0x35, 0xc5, 0x05, 0x2f, 0xec, 0xb5, 0xa4, 0x32, 0x21,
0x56, 0xda, 0xed, 0x6b, 0x52, 0x45, 0x71, 0x4f, 0xf0, 0x91, 0x05, 0x0c, 0x4a, 0x29, 0x8e, 0x17,
0x72, 0x3b, 0x8a, 0x78, 0xaf, 0xc3, 0x65, 0x81, 0x52, 0x4c, 0xd4, 0xd2, 0x76, 0x69, 0x68, 0x3b,
0x93, 0x80, 0xec, 0x42, 0x4d, 0x7b, 0xb7, 0x98, 0xdc, 0xbc, 0xf6, 0xb9, 0xe6, 0xcd, 0xcd, 0xac,
0x24, 0xd1, 0xa4, 0xef, 0x42, 0x55, 0xbd, 0xdb, 0x4a, 0x36, 0xb4, 0x77, 0x85, 0xf5, 0xf7, 0x6e,
0x37, 0x5b, 0xe9, 0x04, 0x91, 0x7f, 0x17, 0x6a, 0xda, 0x23, 0xab, 0xaa, 0x15, 0xe9, 0x27, 0x5e,
0x55, 0x2b, 0xb2, 0xde, 0x64, 0x3d, 0x80, 0x35, 0xa1, 0x1e, 0x39, 0xa1, 0x5f, 0x67, 0x78, 0x48,
0x7a, 0x78, 0x1e, 0xe4, 0xc8, 0x17, 0x50, 0x91, 0x4f, 0xfb, 0x92, 0xf5, 0xec, 0xa7, 0x92, 0x37,
0x37, 0x52, 0x70, 0xd1, 0x94, 0x36, 0x40, 0xf4, 0x48, 0x2b, 0x91, 0x1d, 0x4f, 0x3d, 0x07, 0xab,
0x66, 0x26, 0xe3, 0x45, 0xd7, 0x5d, 0xa8, 0x69, 0xef, 0xb1, 0xaa, 0x31, 0x49, 0xbf, 0xe5, 0xaa,
0xc6, 0x24, 0xeb, 0xf9, 0xd6, 0xef, 0x43, 0x23, 0xf6, 0xb0, 0xaa, 0x5a, 0xc7, 0x59, 0xcf, 0xb6,
0xaa, 0x75, 0x9c, 0xfd, 0x16, 0xeb, 0x2e, 0xd4, 0xb4, 0xc7, 0x4e, 0x55, 0x8b, 0xd2, 0x2f, 0xae,
0xaa, 0x16, 0x65, 0xbc, 0x8d, 0xca, 0x76, 0x43, 0xfc, 0xa5, 0x53, 0xb5, 0x1b, 0x32, 0x9f, 0x4c,
0x55, 0xbb, 0x21, 0xfb, 0x79, 0x54, 0xb6, 0xf4, 0xd4, 0xeb, 0x2a, 0x64, 0x23, 0xa6, 0x95, 0x88,
0x9e, 0x69, 0x51, 0x4b, 0x2f, 0xfd, 0x10, 0xcb, 0x63, 0x58, 0x51, 0x8b, 0x46, 0xbd, 0x8d, 0x12,
0xa8, 0x36, 0x65, 0xbe, 0xc0, 0xb2, 0xd9, 0x4c, 0xa6, 0x3e, 0xc8, 0x91, 0xcf, 0xa0, 0x2c, 0x1e,
0x9c, 0x20, 0x6b, 0xc9, 0x07, 0x28, 0x78, 0x23, 0xd6, 0xb3, 0xdf, 0xa5, 0x20, 0x47, 0xb8, 0xa1,
0xf5, 0x17, 0x21, 0xf4, 0x15, 0x9b, 0xf1, 0x88, 0xc4, 0xe6, 0xeb, 0xd7, 0x25, 0x47, 0x25, 0x26,
0x5f, 0x31, 0xb9, 0x7d, 0x5d, 0xb0, 0xb0, 0x78, 0x89, 0xd7, 0x45, 0x35, 0x7d, 0x0c, 0x75, 0xfd,
0x95, 0x3b, 0xa2, 0xef, 0xc3, 0x64, 0x59, 0xb7, 0x32, 0xd3, 0x44, 0x41, 0x5f, 0xc2, 0xba, 0x1a,
0x6f, 0x3d, 0x72, 0x55, 0x40, 0xee, 0x64, 0xc4, 0xb3, 0x8a, 0x8d, 0xfa, 0xcd, 0x6b, 0x03, 0x5e,
0x3d, 0xc8, 0x21, 0x91, 0x8d, 0x3d, 0x4c, 0x15, 0x11, 0xd9, 0xac, 0xf7, 0xb8, 0x22, 0x22, 0x9b,
0xfd, 0x9a, 0x55, 0x1b, 0x96, 0xb4, 0xc8, 0x5b, 0x83, 0x2b, 0x77, 0xa4, 0xd6, 0x7b, 0x3a, 0x04,
0xff, 0x66, 0x96, 0x92, 0x9e, 0xec, 0x40, 0x4d, 0x0f, 0xde, 0xf5, 0x82, 0xec, 0x1b, 0x5a, 0x92,
0x1e, 0x19, 0xfd, 0x41, 0x8e, 0x1c, 0x40, 0x33, 0x19, 0x6a, 0x57, 0x6d, 0xe1, 0xac, 0xf0, 0xc4,
0x9b, 0x89, 0xc4, 0x58, 0x80, 0x5e, 0xb6, 0x2e, 0x44, 0xd5, 0xfc, 0x4d, 0x59, 0xcf, 0x4f, 0x1e,
0x45, 0x1c, 0x2e, 0x87, 0x41, 0x95, 0x96, 0x48, 0xc5, 0x66, 0xdf, 0xcb, 0x3d, 0xc8, 0x91, 0x3d,
0xa8, 0xc7, 0x22, 0x4d, 0xc6, 0xee, 0x7e, 0x25, 0xba, 0xd9, 0xd2, 0xd3, 0x12, 0xfd, 0x3c, 0x84,
0xc5, 0xb8, 0xd3, 0x89, 0x6a, 0x58, 0xa6, 0x67, 0x8c, 0x9a, 0xbe, 0x6c, 0x4f, 0x15, 0xf2, 0xb3,
0x50, 0x63, 0x34, 0x59, 0x7a, 0x46, 0x12, 0x8d, 0x4e, 0x27, 0xe7, 0x8c, 0xc3, 0x84, 0xd6, 0xbc,
0xf0, 0x57, 0xf3, 0x39, 0xec, 0xd7, 0x77, 0xf8, 0x2b, 0xfa, 0xd2, 0x39, 0x8e, 0xcd, 0xff, 0xab,
0x16, 0x42, 0xf6, 0x78, 0xe5, 0x43, 0x8f, 0x87, 0x74, 0xb8, 0xa9, 0xe1, 0x08, 0xd8, 0xab, 0xb5,
0xa1, 0xcd, 0xdb, 0x20, 0xf2, 0xc4, 0xd6, 0xe0, 0x2b, 0x96, 0x45, 0x3e, 0x05, 0x88, 0x9c, 0x92,
0x49, 0xc2, 0xef, 0x55, 0x6d, 0xa8, 0x0c, 0xbf, 0xe5, 0x0e, 0xdf, 0xef, 0xca, 0xf1, 0x56, 0x3f,
0x92, 0xe3, 0x3e, 0xc0, 0xb1, 0x23, 0x39, 0x59, 0xcc, 0x47, 0xd0, 0x38, 0xf0, 0xbc, 0x67, 0xf3,
0x99, 0xba, 0xaa, 0x13, 0x77, 0xfb, 0xda, 0xb7, 0x83, 0xf3, 0xcd, 0x44, 0xb3, 0x48, 0x1b, 0x96,
0x15, 0x89, 0x88, 0x3c, 0x7f, 0xe3, 0x48, 0x31, 0xc2, 0x90, 0x28, 0xe0, 0x41, 0x8e, 0x3c, 0x84,
0xfa, 0x2e, 0x1d, 0x61, 0x2c, 0x1c, 0x74, 0x03, 0x5a, 0x89, 0xb9, 0x94, 0x70, 0xff, 0xa1, 0xcd,
0x46, 0x0c, 0x28, 0x49, 0x5c, 0xe4, 0xe8, 0xa6, 0x9f, 0x19, 0x71, 0x6f, 0xb1, 0x18, 0x89, 0x4b,
0x39, 0xbb, 0x7d, 0x09, 0xcb, 0x29, 0x67, 0x2f, 0x45, 0xdd, 0xae, 0x73, 0x40, 0xdb, 0xbc, 0x7b,
0x3d, 0x82, 0x28, 0xf7, 0x7b, 0xd0, 0xe0, 0x81, 0xf2, 0x4f, 0x28, 0xbf, 0x36, 0x9e, 0x08, 0x83,
0xa8, 0xdf, 0x49, 0x4f, 0x92, 0x24, 0x9e, 0xe1, 0x31, 0x3e, 0xd9, 0xa5, 0x5d, 0xca, 0x56, 0xf3,
0x9a, 0xbe, 0x28, 0xae, 0xe6, 0x35, 0xeb, 0xfe, 0xf7, 0xe7, 0x50, 0x7b, 0x4c, 0x43, 0x79, 0xcd,
0x59, 0xf1, 0x47, 0x89, 0x7b, 0xcf, 0x9b, 0x19, 0x97, 0xd3, 0xc9, 0x27, 0x98, 0x55, 0x85, 0xec,
0x58, 0xd7, 0x6a, 0xd1, 0xb3, 0x2e, 0x25, 0xe0, 0x8c, 0xfb, 0xd0, 0xa2, 0x09, 0xa9, 0x86, 0xa7,
0xa3, 0x47, 0xa9, 0x86, 0x67, 0x05, 0x1f, 0xfa, 0x59, 0x3e, 0x02, 0xda, 0xc5, 0xea, 0x88, 0x05,
0x4b, 0xde, 0xc1, 0x56, 0xcd, 0xd7, 0xd1, 0x1f, 0x01, 0x0c, 0x42, 0x6f, 0xb6, 0x6b, 0xd3, 0xa9,
0xe7, 0x46, 0x34, 0x21, 0xba, 0xd2, 0x1b, 0x6d, 0x44, 0xed, 0x5e, 0x2f, 0xf9, 0x4a, 0xe3, 0x4d,
0x63, 0x53, 0x22, 0xa7, 0xfd, 0xda, 0x5b, 0xbf, 0xaa, 0x3b, 0x19, 0x37, 0x7f, 0x91, 0x48, 0x40,
0xe4, 0x4b, 0xa7, 0x38, 0xcd, 0x94, 0x9b, 0x9e, 0xda, 0xeb, 0x19, 0x8e, 0x77, 0xdf, 0x85, 0x6a,
0xe4, 0x84, 0xb4, 0x11, 0x85, 0x36, 0x8b, 0xb9, 0x2c, 0x29, 0xea, 0x9d, 0x76, 0x00, 0xea, 0xc1,
0x0a, 0x6f, 0x8e, 0x3a, 0xfe, 0xf0, 0xae, 0xa6, 0x7a, 0x71, 0x2e, 0xed, 0x79, 0xa3, 0xf6, 0x4f,
0x96, 0xff, 0x08, 0xdb, 0x3f, 0x29, 0x07, 0x03, 0xb5, 0x7f, 0xae, 0x73, 0x2c, 0x51, 0xfb, 0xe7,
0x7a, 0xdf, 0x84, 0x1e, 0xac, 0x64, 0xb8, 0x0a, 0x90, 0x37, 0xa4, 0x60, 0x73, 0xad, 0x1b, 0xc1,
0x66, 0xa6, 0x49, 0x99, 0x0c, 0x61, 0x83, 0xe7, 0x69, 0x4f, 0x26, 0x09, 0xcb, 0xf4, 0xeb, 0x5a,
0x86, 0x0c, 0x6b, 0x7b, 0x8c, 0x95, 0x49, 0x58, 0xdc, 0x7b, 0xd0, 0x4c, 0x1a, 0x75, 0xc9, 0xf5,
0xe8, 0x9b, 0x77, 0x62, 0x2c, 0x7b, 0xda, 0x10, 0x4c, 0xbe, 0x54, 0xa6, 0xe5, 0x44, 0x1b, 0xef,
0x44, 0x2f, 0xa7, 0x66, 0x1a, 0xc2, 0x95, 0x34, 0x90, 0x69, 0x99, 0x26, 0x3f, 0x07, 0x1b, 0xc9,
0x15, 0x2d, 0x4b, 0xbe, 0x9b, 0x35, 0x5c, 0xd7, 0xb2, 0x72, 0xf1, 0x0e, 0x3d, 0xc8, 0x31, 0x42,
0xac, 0x1b, 0x80, 0xd5, 0x42, 0xca, 0xb0, 0x44, 0xab, 0x85, 0x94, 0x69, 0x31, 0x3e, 0x82, 0xa5,
0x84, 0xed, 0x57, 0xb1, 0xc1, 0xd9, 0xd6, 0x62, 0xc5, 0x06, 0x5f, 0x67, 0x32, 0x1e, 0x40, 0x33,
0x69, 0xd5, 0x55, 0x73, 0x7d, 0x8d, 0xa5, 0x78, 0xf3, 0xce, 0xb5, 0xe9, 0xf1, 0x66, 0x6a, 0xf6,
0xcf, 0x58, 0x33, 0xd3, 0x56, 0xdb, 0x58, 0x33, 0x33, 0xac, 0xaf, 0xdb, 0xef, 0xfc, 0xfc, 0xb7,
0xce, 0x9c, 0xf0, 0x7c, 0x7e, 0xb2, 0x35, 0xf2, 0xa6, 0x1f, 0x4c, 0xa4, 0x56, 0x43, 0xc4, 0x61,
0xf8, 0x60, 0xe2, 0x8e, 0x3f, 0xc0, 0x02, 0x4e, 0x16, 0x66, 0xbe, 0x17, 0x7a, 0x1f, 0xfd, 0xbf,
0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x34, 0x7a, 0xb4, 0x1e, 0x96, 0x00, 0x00,
// 12745 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xbd, 0x5d, 0x6c, 0x23, 0x59,
0x76, 0x18, 0xdc, 0xfc, 0x13, 0xc9, 0x43, 0x52, 0xa2, 0xae, 0xfe, 0xd8, 0xea, 0xe9, 0xe9, 0x9e,
0x9a, 0xd9, 0x99, 0xde, 0x9e, 0x19, 0x4d, 0x4f, 0xcf, 0xf4, 0xfc, 0xec, 0x7c, 0x5e, 0x2f, 0x25,
0x51, 0x2d, 0x6e, 0x4b, 0xa4, 0xb6, 0x48, 0xcd, 0xb8, 0x0d, 0xdb, 0xe5, 0x12, 0x79, 0x25, 0xd5,
0xd7, 0x64, 0x15, 0xb7, 0xaa, 0xa8, 0x96, 0x36, 0x08, 0xe0, 0x07, 0xc7, 0x0e, 0x0c, 0x27, 0x80,
0x81, 0x38, 0x40, 0x90, 0x18, 0x49, 0x90, 0x20, 0x79, 0x33, 0x0c, 0xd8, 0x79, 0x4a, 0x1e, 0xf2,
0x14, 0x20, 0x40, 0x02, 0x23, 0x40, 0x8c, 0xfc, 0x3c, 0x24, 0x08, 0x90, 0x38, 0x40, 0x0c, 0xc4,
0x06, 0xfc, 0x98, 0x04, 0x09, 0xee, 0xb9, 0x3f, 0x75, 0xeb, 0x47, 0xdd, 0x3d, 0xeb, 0xd9, 0x7d,
0x91, 0x58, 0xe7, 0x9c, 0xfb, 0x7f, 0xef, 0xb9, 0xe7, 0x9c, 0x7b, 0xee, 0xb9, 0x50, 0xf5, 0x67,
0xa3, 0xad, 0x99, 0xef, 0x85, 0x1e, 0x29, 0x4d, 0x5c, 0x7f, 0x36, 0x32, 0xfe, 0x38, 0x07, 0xc5,
0xe3, 0xf0, 0xd2, 0x23, 0x8f, 0xa0, 0x6e, 0x8f, 0xc7, 0x3e, 0x0d, 0x02, 0x2b, 0xbc, 0x9a, 0xd1,
0x56, 0xee, 0x6e, 0xee, 0xde, 0xe2, 0x43, 0xb2, 0x85, 0x64, 0x5b, 0x6d, 0x8e, 0x1a, 0x5e, 0xcd,
0xa8, 0x59, 0xb3, 0xa3, 0x0f, 0xd2, 0x82, 0xb2, 0xf8, 0x6c, 0xe5, 0xef, 0xe6, 0xee, 0x55, 0x4d,
0xf9, 0x49, 0x6e, 0x03, 0xd8, 0x53, 0x6f, 0xee, 0x86, 0x56, 0x60, 0x87, 0xad, 0xc2, 0xdd, 0xdc,
0xbd, 0x82, 0x59, 0xe5, 0x90, 0x81, 0x1d, 0x92, 0x5b, 0x50, 0x9d, 0x3d, 0xb3, 0x82, 0x91, 0xef,
0xcc, 0xc2, 0x56, 0x11, 0x93, 0x56, 0x66, 0xcf, 0x06, 0xf8, 0x4d, 0xde, 0x85, 0x8a, 0x37, 0x0f,
0x67, 0x9e, 0xe3, 0x86, 0xad, 0xd2, 0xdd, 0xdc, 0xbd, 0xda, 0xc3, 0x25, 0x51, 0x91, 0xfe, 0x3c,
0x3c, 0x62, 0x60, 0x53, 0x11, 0x90, 0xb7, 0xa0, 0x31, 0xf2, 0xdc, 0x53, 0xc7, 0x9f, 0xda, 0xa1,
0xe3, 0xb9, 0x41, 0x6b, 0x01, 0xcb, 0x8a, 0x03, 0x8d, 0x7f, 0x91, 0x87, 0xda, 0xd0, 0xb7, 0xdd,
0xc0, 0x1e, 0x31, 0x00, 0xd9, 0x80, 0x72, 0x78, 0x69, 0x9d, 0xdb, 0xc1, 0x39, 0x36, 0xb5, 0x6a,
0x2e, 0x84, 0x97, 0xfb, 0x76, 0x70, 0x4e, 0xd6, 0x61, 0x81, 0xd7, 0x12, 0x1b, 0x54, 0x30, 0xc5,
0x17, 0x79, 0x17, 0x96, 0xdd, 0xf9, 0xd4, 0x8a, 0x17, 0xc5, 0x9a, 0x55, 0x32, 0x9b, 0xee, 0x7c,
0xba, 0xa3, 0xc3, 0x59, 0xe3, 0x4f, 0x26, 0xde, 0xe8, 0x19, 0x2f, 0x80, 0x37, 0xaf, 0x8a, 0x10,
0x2c, 0xe3, 0x0d, 0xa8, 0x0b, 0x34, 0x75, 0xce, 0xce, 0x79, 0x1b, 0x4b, 0x66, 0x8d, 0x13, 0x20,
0x88, 0xe5, 0x10, 0x3a, 0x53, 0x6a, 0x05, 0xa1, 0x3d, 0x9d, 0x89, 0x26, 0x55, 0x19, 0x64, 0xc0,
0x00, 0x88, 0xf6, 0x42, 0x7b, 0x62, 0x9d, 0x52, 0x1a, 0xb4, 0xca, 0x02, 0xcd, 0x20, 0x7b, 0x94,
0x06, 0xe4, 0x5b, 0xb0, 0x38, 0xa6, 0x41, 0x68, 0x89, 0xc1, 0xa0, 0x41, 0xab, 0x72, 0xb7, 0x70,
0xaf, 0x6a, 0x36, 0x18, 0xb4, 0x2d, 0x81, 0xe4, 0x35, 0x00, 0xdf, 0x7e, 0x6e, 0xb1, 0x8e, 0xa0,
0x97, 0xad, 0x2a, 0x1f, 0x05, 0xdf, 0x7e, 0x3e, 0xbc, 0xdc, 0xa7, 0x97, 0x64, 0x15, 0x4a, 0x13,
0xfb, 0x84, 0x4e, 0x5a, 0x80, 0x08, 0xfe, 0x61, 0x84, 0xb0, 0xfe, 0x98, 0x86, 0x5a, 0x57, 0x06,
0x26, 0xfd, 0xe1, 0x9c, 0x06, 0x21, 0x6b, 0x55, 0x10, 0xda, 0x7e, 0x28, 0x5b, 0x95, 0xe3, 0xad,
0x42, 0x58, 0xd4, 0x2a, 0xea, 0x8e, 0x25, 0x41, 0x1e, 0x09, 0xaa, 0xd4, 0x1d, 0x0b, 0x34, 0x9b,
0x4d, 0xa3, 0x11, 0x76, 0x7e, 0x41, 0xcc, 0x26, 0xfe, 0x69, 0x1c, 0x00, 0xd1, 0x8a, 0xdc, 0xa5,
0xa1, 0xed, 0x4c, 0x02, 0xf2, 0x09, 0xd4, 0x43, 0xad, 0x22, 0xad, 0xdc, 0xdd, 0xc2, 0xbd, 0x9a,
0x9a, 0xb4, 0x5a, 0x02, 0x33, 0x46, 0x67, 0x9c, 0x43, 0x65, 0x8f, 0xd2, 0x03, 0x67, 0xea, 0x84,
0x64, 0x1d, 0x4a, 0xa7, 0xce, 0x25, 0x1d, 0x63, 0x75, 0x0b, 0xfb, 0x37, 0x4c, 0xfe, 0x49, 0xee,
0x00, 0xe0, 0x0f, 0x6b, 0xaa, 0xe6, 0xef, 0xfe, 0x0d, 0xb3, 0x8a, 0xb0, 0xc3, 0xc0, 0x0e, 0xc9,
0x26, 0x94, 0x67, 0xd4, 0x1f, 0x51, 0x39, 0x53, 0xf6, 0x6f, 0x98, 0x12, 0xb0, 0x5d, 0x86, 0xd2,
0x84, 0xe5, 0x6e, 0xfc, 0x8f, 0x12, 0xd4, 0x06, 0xd4, 0x1d, 0xcb, 0x3e, 0x22, 0x50, 0x64, 0x43,
0x80, 0x85, 0xd5, 0x4d, 0xfc, 0x4d, 0xde, 0x84, 0x1a, 0x0e, 0x56, 0x10, 0xfa, 0x8e, 0x7b, 0xc6,
0xd7, 0xd1, 0x76, 0xbe, 0x95, 0x33, 0x81, 0x81, 0x07, 0x08, 0x25, 0x4d, 0x28, 0xd8, 0x53, 0xb9,
0x8e, 0xd8, 0x4f, 0x72, 0x13, 0x2a, 0xf6, 0x34, 0xe4, 0xd5, 0xab, 0x23, 0xb8, 0x6c, 0x4f, 0x43,
0xac, 0xda, 0x1b, 0x50, 0x9f, 0xd9, 0x57, 0x53, 0xea, 0x86, 0xd1, 0x04, 0xac, 0x9b, 0x35, 0x01,
0xc3, 0x29, 0xf8, 0x10, 0x56, 0x74, 0x12, 0x59, 0x78, 0x49, 0x15, 0xbe, 0xac, 0x51, 0x8b, 0x3a,
0xbc, 0x03, 0x4b, 0x32, 0x8d, 0xcf, 0xdb, 0x83, 0x13, 0xb3, 0x6a, 0x2e, 0x0a, 0xb0, 0x6c, 0xe5,
0x3d, 0x68, 0x9e, 0x3a, 0xae, 0x3d, 0xb1, 0x46, 0x93, 0xf0, 0xc2, 0x1a, 0xd3, 0x49, 0x68, 0xe3,
0x1c, 0x2d, 0x99, 0x8b, 0x08, 0xdf, 0x99, 0x84, 0x17, 0xbb, 0x0c, 0x4a, 0xde, 0x83, 0xea, 0x29,
0xa5, 0x16, 0x76, 0x56, 0xab, 0x12, 0x5b, 0xea, 0x72, 0x84, 0xcc, 0xca, 0xa9, 0x1c, 0xab, 0xf7,
0xa0, 0xe9, 0xcd, 0xc3, 0x33, 0xcf, 0x71, 0xcf, 0xac, 0xd1, 0xb9, 0xed, 0x5a, 0xce, 0x18, 0x67,
0x6d, 0x71, 0x3b, 0xff, 0x20, 0x67, 0x2e, 0x4a, 0xdc, 0xce, 0xb9, 0xed, 0x76, 0xc7, 0xe4, 0x6d,
0x58, 0x9a, 0xd8, 0x41, 0x68, 0x9d, 0x7b, 0x33, 0x6b, 0x36, 0x3f, 0x79, 0x46, 0xaf, 0x5a, 0x0d,
0xec, 0x88, 0x06, 0x03, 0xef, 0x7b, 0xb3, 0x23, 0x04, 0xb2, 0x49, 0x89, 0xf5, 0xe4, 0x95, 0x60,
0x93, 0xbd, 0x61, 0x56, 0x19, 0x84, 0x17, 0xfa, 0x14, 0x56, 0x70, 0x78, 0x46, 0xf3, 0x20, 0xf4,
0xa6, 0x96, 0x4f, 0x47, 0x9e, 0x3f, 0x0e, 0x5a, 0x35, 0x9c, 0x6b, 0xdf, 0x16, 0x95, 0xd5, 0xc6,
0x78, 0x6b, 0x97, 0x06, 0xe1, 0x0e, 0x12, 0x9b, 0x9c, 0xb6, 0xe3, 0x86, 0xfe, 0x95, 0xb9, 0x3c,
0x4e, 0xc2, 0xc9, 0x7b, 0x40, 0xec, 0xc9, 0xc4, 0x7b, 0x6e, 0x05, 0x74, 0x72, 0x6a, 0x89, 0x4e,
0x6c, 0x2d, 0xde, 0xcd, 0xdd, 0xab, 0x98, 0x4d, 0xc4, 0x0c, 0xe8, 0xe4, 0xf4, 0x88, 0xc3, 0xc9,
0x27, 0x80, 0xcb, 0xd7, 0x3a, 0xa5, 0x76, 0x38, 0xf7, 0x69, 0xd0, 0x5a, 0xba, 0x5b, 0xb8, 0xb7,
0xf8, 0x70, 0x59, 0xf5, 0x17, 0x82, 0xb7, 0x9d, 0xd0, 0xac, 0x33, 0x3a, 0xf1, 0x1d, 0xe8, 0xb3,
0x81, 0xf1, 0x83, 0x56, 0x33, 0x36, 0x1b, 0x18, 0x37, 0xd8, 0xdc, 0x85, 0xf5, 0xec, 0x5a, 0xb3,
0x79, 0xc7, 0x3a, 0x8e, 0xcd, 0xd7, 0xa2, 0xc9, 0x7e, 0x32, 0xb6, 0x70, 0x61, 0x4f, 0xe6, 0x14,
0x27, 0x6a, 0xdd, 0xe4, 0x1f, 0xdf, 0xc9, 0x7f, 0x96, 0x33, 0xfe, 0x20, 0x07, 0x75, 0xde, 0x11,
0xc1, 0xcc, 0x73, 0x03, 0x4a, 0xde, 0x84, 0x86, 0x2c, 0x99, 0xfa, 0xbe, 0xe7, 0x0b, 0x56, 0x2b,
0xab, 0xd3, 0x61, 0x30, 0xf2, 0x6d, 0x68, 0x4a, 0xa2, 0x99, 0x4f, 0x9d, 0xa9, 0x7d, 0x26, 0xb3,
0x96, 0xb3, 0xed, 0x48, 0x80, 0xc9, 0x87, 0x51, 0x7e, 0xbe, 0x37, 0x0f, 0x29, 0x2e, 0x87, 0xda,
0xc3, 0xba, 0xe8, 0x01, 0x93, 0xc1, 0x54, 0xee, 0xf8, 0xf5, 0x0a, 0x4b, 0xc1, 0xf8, 0xed, 0x1c,
0x10, 0x56, 0xed, 0xa1, 0xc7, 0x33, 0x88, 0xd8, 0x59, 0x2c, 0x65, 0xee, 0x95, 0x17, 0x51, 0xfe,
0x45, 0x8b, 0xc8, 0x80, 0x12, 0xaf, 0x7b, 0x31, 0xa3, 0xee, 0x1c, 0xf5, 0xfd, 0x62, 0xa5, 0xd0,
0x2c, 0x1a, 0xff, 0xb1, 0x00, 0xab, 0x6c, 0x2a, 0xbb, 0x74, 0xd2, 0x1e, 0x8d, 0xe8, 0x4c, 0x2d,
0xaf, 0x3b, 0x50, 0x73, 0xbd, 0x31, 0x95, 0x93, 0x9a, 0x57, 0x0c, 0x18, 0x48, 0x9b, 0xd1, 0xe7,
0xb6, 0xe3, 0xf2, 0x8a, 0xf3, 0xce, 0xac, 0x22, 0x04, 0xab, 0xfd, 0x36, 0x2c, 0xcd, 0xa8, 0x3b,
0xd6, 0x57, 0x51, 0x81, 0x2f, 0x0c, 0x01, 0x16, 0x0b, 0xe8, 0x0e, 0xd4, 0x4e, 0xe7, 0x9c, 0x8e,
0xf1, 0x9e, 0x22, 0xce, 0x01, 0x10, 0xa0, 0x36, 0x67, 0x41, 0xb3, 0x79, 0x70, 0x8e, 0xd8, 0x12,
0x62, 0xcb, 0xec, 0x9b, 0xa1, 0x6e, 0x03, 0x8c, 0xe7, 0x41, 0x28, 0x16, 0xd5, 0x02, 0x22, 0xab,
0x0c, 0xc2, 0x17, 0xd5, 0xfb, 0xb0, 0x32, 0xb5, 0x2f, 0x2d, 0x9c, 0x3b, 0x96, 0xe3, 0x5a, 0xa7,
0x13, 0xdc, 0x11, 0xca, 0x48, 0xd7, 0x9c, 0xda, 0x97, 0x5f, 0x32, 0x4c, 0xd7, 0xdd, 0x43, 0x38,
0xe3, 0x3c, 0x23, 0xde, 0x13, 0x96, 0x4f, 0x03, 0xea, 0x5f, 0x50, 0x64, 0x16, 0x45, 0x73, 0x51,
0x80, 0x4d, 0x0e, 0x65, 0x35, 0x9a, 0xb2, 0x76, 0x87, 0x93, 0x11, 0xe7, 0x0c, 0x66, 0x79, 0xea,
0xb8, 0xfb, 0xe1, 0x64, 0xc4, 0x36, 0x3b, 0xc6, 0x6a, 0x66, 0xd4, 0xb7, 0x9e, 0x3d, 0xc7, 0x65,
0x5e, 0x44, 0xd6, 0x72, 0x44, 0xfd, 0x27, 0xcf, 0x99, 0x3c, 0x32, 0x0a, 0x90, 0x57, 0xd9, 0x57,
0xad, 0x1a, 0xf2, 0x80, 0xca, 0x28, 0x60, 0x5c, 0xca, 0xbe, 0x62, 0xeb, 0x94, 0xd5, 0xd6, 0xc6,
0x51, 0xa0, 0x63, 0xcc, 0x3e, 0x40, 0xa6, 0xdb, 0xc0, 0xca, 0xb6, 0x05, 0x82, 0x95, 0x13, 0xb0,
0x59, 0x2f, 0x2b, 0x7b, 0x3a, 0xb1, 0xcf, 0x02, 0xe4, 0x3a, 0x0d, 0xb3, 0x2e, 0x80, 0x7b, 0x0c,
0x66, 0xfc, 0x79, 0x1e, 0xd6, 0x12, 0x83, 0x2b, 0x16, 0x0d, 0x13, 0x40, 0x10, 0x82, 0x03, 0x5b,
0x31, 0xc5, 0x57, 0xd6, 0xa8, 0xe5, 0xb3, 0x46, 0x6d, 0x15, 0x4a, 0x7c, 0xb1, 0xf1, 0x2d, 0x94,
0x7f, 0xb0, 0x55, 0x36, 0x9f, 0x9d, 0xfa, 0x1e, 0x93, 0xc7, 0xce, 0xe7, 0xe1, 0xd8, 0x7b, 0xee,
0x0a, 0xb9, 0x64, 0x49, 0xc0, 0x07, 0x02, 0x1c, 0xef, 0x8a, 0x52, 0xa2, 0x2b, 0xee, 0x40, 0x4d,
0x8c, 0x00, 0xca, 0x75, 0x7c, 0x60, 0x41, 0x80, 0x98, 0x60, 0xf7, 0x2e, 0x10, 0x35, 0x9e, 0x16,
0xeb, 0x35, 0xdc, 0xa0, 0xf8, 0xc0, 0x2e, 0x39, 0x62, 0x40, 0x0f, 0xed, 0x4b, 0xdc, 0xa8, 0xde,
0x82, 0x45, 0x46, 0xc2, 0xfa, 0xd3, 0xe2, 0xfb, 0x7e, 0x85, 0xf7, 0xd5, 0xd4, 0xbe, 0x64, 0x9d,
0xb9, 0x83, 0xa2, 0xd7, 0xeb, 0x50, 0x93, 0x83, 0x6a, 0x39, 0xae, 0x18, 0xd7, 0xaa, 0x18, 0xd7,
0xae, 0xcb, 0xb6, 0x1b, 0x86, 0xe7, 0xfd, 0x64, 0x8d, 0xe9, 0x2c, 0x3c, 0x17, 0x6c, 0x7c, 0x71,
0xea, 0xb8, 0xbc, 0x7b, 0x77, 0x19, 0xd4, 0xf8, 0x9d, 0x1c, 0xd4, 0x45, 0xaf, 0xa3, 0x18, 0x49,
0xb6, 0x80, 0xc8, 0x29, 0x1e, 0x5e, 0x3a, 0x63, 0xeb, 0xe4, 0x2a, 0xa4, 0x01, 0x5f, 0x51, 0xfb,
0x37, 0xcc, 0xa6, 0xc0, 0x0d, 0x2f, 0x9d, 0xf1, 0x36, 0xc3, 0x90, 0xfb, 0xd0, 0x8c, 0xd1, 0x07,
0xa1, 0xcf, 0x97, 0xfb, 0xfe, 0x0d, 0x73, 0x51, 0xa3, 0x1e, 0x84, 0x3e, 0x63, 0x20, 0x4c, 0x48,
0x9d, 0x87, 0x96, 0xe3, 0x8e, 0xe9, 0x25, 0x8e, 0x47, 0xc3, 0xac, 0x71, 0x58, 0x97, 0x81, 0xb6,
0x17, 0xa1, 0xae, 0x67, 0x67, 0x9c, 0x41, 0x45, 0x4a, 0xb8, 0x28, 0xe2, 0x25, 0xaa, 0x64, 0x56,
0x43, 0x55, 0x93, 0x9b, 0x50, 0x89, 0xd7, 0xc0, 0x2c, 0x87, 0xaf, 0x5c, 0xb0, 0xf1, 0x5d, 0x68,
0x1e, 0xb0, 0x81, 0x70, 0xd9, 0x4a, 0x16, 0x12, 0xfb, 0x3a, 0x2c, 0x68, 0x1c, 0xa5, 0x6a, 0x8a,
0x2f, 0x26, 0xb3, 0x9c, 0x7b, 0x41, 0x28, 0x4a, 0xc1, 0xdf, 0xc6, 0x6f, 0xe5, 0x81, 0x74, 0x82,
0xd0, 0x99, 0xda, 0x21, 0xdd, 0xa3, 0x8a, 0x67, 0xf6, 0xa1, 0xce, 0x72, 0x1b, 0x7a, 0x6d, 0x2e,
0x42, 0x73, 0x81, 0xec, 0x5d, 0xc1, 0xe3, 0xd2, 0x09, 0xb6, 0x74, 0x6a, 0xbe, 0x4d, 0xc6, 0x32,
0x60, 0xd3, 0x2d, 0xb4, 0xfd, 0x33, 0x1a, 0xa2, 0xe0, 0x2d, 0x24, 0x46, 0xe0, 0x20, 0x26, 0x72,
0xb3, 0xc9, 0xca, 0xc6, 0x9e, 0x61, 0xa5, 0x38, 0xce, 0x38, 0x00, 0xc3, 0x05, 0x4c, 0x66, 0x0f,
0xd8, 0xe2, 0xb0, 0xe6, 0xae, 0x90, 0xdb, 0xe9, 0x18, 0x67, 0x7d, 0xc5, 0x6c, 0x22, 0xe2, 0x38,
0x82, 0x6f, 0xfe, 0x2c, 0x2c, 0xa7, 0x6a, 0xa3, 0x6f, 0x7f, 0xd5, 0x8c, 0xed, 0xaf, 0xa0, 0x6f,
0x7f, 0xbf, 0x9e, 0x83, 0x95, 0x58, 0x13, 0xc5, 0x82, 0xde, 0x80, 0x32, 0x63, 0x3c, 0x6c, 0x19,
0xe4, 0xb8, 0x4a, 0x71, 0x4a, 0x71, 0xa9, 0x7c, 0x04, 0xab, 0xa7, 0x94, 0xfa, 0x76, 0x88, 0x48,
0xe4, 0x4c, 0x6c, 0xb0, 0x79, 0xce, 0x7c, 0xff, 0x10, 0xf8, 0x81, 0x1d, 0x1e, 0x51, 0x9f, 0x0d,
0x3c, 0x31, 0xa0, 0x21, 0x89, 0x2f, 0x90, 0xba, 0x80, 0xcb, 0xa1, 0x16, 0x20, 0xc9, 0x97, 0x0c,
0x64, 0xfc, 0x49, 0x1e, 0x96, 0xd8, 0x8e, 0x76, 0x68, 0xbb, 0x57, 0x72, 0x68, 0x0e, 0x32, 0x87,
0xe6, 0x9e, 0x26, 0xbf, 0x68, 0xd4, 0x5f, 0x77, 0x5c, 0x0a, 0xa9, 0x71, 0x49, 0x55, 0xb3, 0x98,
0xaa, 0x26, 0x79, 0x0b, 0xea, 0xb1, 0x76, 0x97, 0x54, 0xbb, 0x21, 0x88, 0x1a, 0xac, 0xd4, 0x90,
0x05, 0x4d, 0x0d, 0x89, 0x8f, 0x7b, 0xf9, 0x55, 0xc6, 0xbd, 0xf2, 0x93, 0x1a, 0xf7, 0xb7, 0xa1,
0x19, 0x75, 0x9f, 0x18, 0x73, 0x02, 0x45, 0xb6, 0x1a, 0x45, 0x06, 0xf8, 0xdb, 0xf8, 0x87, 0x79,
0x4e, 0xb8, 0xe3, 0x39, 0x91, 0xd2, 0x44, 0xa0, 0x88, 0x42, 0x99, 0x20, 0x64, 0xbf, 0xaf, 0x55,
0x41, 0x7f, 0x8a, 0x9d, 0x7e, 0x13, 0x2a, 0x01, 0xeb, 0x40, 0x7b, 0xc2, 0xfb, 0xbd, 0x62, 0x96,
0xd9, 0x77, 0x7b, 0x32, 0x89, 0xc6, 0xa3, 0x7c, 0xed, 0x78, 0x54, 0x5e, 0x65, 0x3c, 0xaa, 0xd9,
0xe3, 0x61, 0xbc, 0x03, 0xcb, 0x5a, 0x2f, 0xbd, 0xa0, 0x3f, 0xcf, 0x81, 0x1c, 0x38, 0x41, 0x78,
0xec, 0xb2, 0x2c, 0x94, 0x70, 0x14, 0xab, 0x48, 0x2e, 0x51, 0x11, 0x86, 0xb4, 0x2f, 0x05, 0x32,
0x2f, 0x90, 0xf6, 0x25, 0x47, 0x5e, 0xaf, 0x7d, 0x7e, 0x06, 0x2b, 0xb1, 0x92, 0x44, 0xa5, 0xde,
0x80, 0xd2, 0x3c, 0xbc, 0xf4, 0xa4, 0xde, 0x59, 0x13, 0x6b, 0xe9, 0x38, 0xbc, 0xf4, 0x4c, 0x8e,
0x31, 0x8e, 0x61, 0xb9, 0x47, 0x9f, 0x0b, 0x0e, 0x2b, 0xab, 0xf8, 0x36, 0x14, 0x5f, 0x62, 0x63,
0x41, 0xbc, 0x5e, 0xa1, 0x7c, 0xbc, 0x42, 0x5b, 0x40, 0xf4, 0x6c, 0x45, 0x7d, 0x34, 0x63, 0x4c,
0x2e, 0x66, 0x8c, 0x31, 0xde, 0x06, 0x32, 0x70, 0xce, 0xdc, 0x43, 0x1a, 0x04, 0xf6, 0x99, 0xe2,
0xd6, 0x4d, 0x28, 0x4c, 0x83, 0x33, 0xb1, 0xb5, 0xb0, 0x9f, 0xc6, 0x47, 0xb0, 0x12, 0xa3, 0x13,
0x19, 0xbf, 0x06, 0xd5, 0xc0, 0x39, 0x73, 0x51, 0x9f, 0x10, 0x59, 0x47, 0x00, 0x63, 0x0f, 0x56,
0xbf, 0xa4, 0xbe, 0x73, 0x7a, 0xf5, 0xb2, 0xec, 0xe3, 0xf9, 0xe4, 0x93, 0xf9, 0x74, 0x60, 0x2d,
0x91, 0x8f, 0x28, 0x9e, 0x2f, 0x3d, 0x31, 0xfa, 0x15, 0x93, 0x7f, 0x68, 0xdb, 0x55, 0x5e, 0xdf,
0xae, 0x0c, 0x0f, 0xc8, 0x8e, 0xe7, 0xba, 0x74, 0x14, 0x1e, 0x51, 0xea, 0xcb, 0xca, 0xbc, 0xab,
0xad, 0xb3, 0xda, 0xc3, 0x0d, 0xd1, 0xe7, 0xc9, 0x3d, 0x50, 0x2c, 0x40, 0x02, 0xc5, 0x19, 0xf5,
0xa7, 0x98, 0x71, 0xc5, 0xc4, 0xdf, 0xac, 0x73, 0x43, 0x67, 0x4a, 0xbd, 0x79, 0x28, 0x38, 0xae,
0xfc, 0x34, 0xd6, 0x60, 0x25, 0x56, 0x20, 0xaf, 0xb5, 0xf1, 0x00, 0xd6, 0x76, 0x9d, 0x60, 0x94,
0xae, 0xca, 0x06, 0x94, 0x67, 0xf3, 0x13, 0x2b, 0xbe, 0xd1, 0x3e, 0xa1, 0x57, 0x46, 0x0b, 0xd6,
0x93, 0x29, 0x44, 0x5e, 0xbf, 0x96, 0x87, 0xe2, 0xfe, 0xf0, 0x60, 0x87, 0x6c, 0x42, 0xc5, 0x71,
0x47, 0xde, 0x94, 0xa9, 0x19, 0xbc, 0x37, 0xd4, 0xf7, 0xb5, 0x6c, 0xe3, 0x16, 0x54, 0x51, 0x3b,
0x99, 0x78, 0xa3, 0x67, 0x42, 0xd0, 0xaf, 0x30, 0xc0, 0x81, 0x37, 0x7a, 0xc6, 0x96, 0x26, 0xbd,
0x9c, 0x39, 0x3e, 0x1a, 0xae, 0xa4, 0x61, 0xa6, 0xc8, 0x25, 0xdb, 0x08, 0x11, 0x99, 0x6f, 0x84,
0x10, 0xc6, 0xc4, 0x0a, 0x2e, 0xf1, 0x57, 0xcf, 0x51, 0x08, 0x1b, 0xd3, 0x4b, 0xf2, 0x3e, 0x90,
0x53, 0xcf, 0x7f, 0x6e, 0xfb, 0x4a, 0x48, 0x75, 0x05, 0xdb, 0x2e, 0x9a, 0xcb, 0x11, 0x46, 0x08,
0x60, 0xe4, 0x21, 0xac, 0x69, 0xe4, 0x5a, 0xc6, 0x5c, 0x58, 0x5c, 0x89, 0x90, 0xfb, 0xb2, 0x08,
0xe3, 0x57, 0xf3, 0x40, 0x44, 0xfa, 0x1d, 0xcf, 0x0d, 0x42, 0xdf, 0x76, 0xdc, 0x30, 0x88, 0x8b,
0xac, 0xb9, 0x84, 0xc8, 0x7a, 0x0f, 0x9a, 0x28, 0x30, 0xeb, 0x72, 0x6b, 0x3e, 0xd2, 0x1e, 0xcc,
0x48, 0x76, 0x7d, 0x0b, 0x16, 0x23, 0xa5, 0x45, 0xd9, 0x2d, 0x8b, 0x66, 0x5d, 0x29, 0x2e, 0x8c,
0xea, 0x03, 0x58, 0x65, 0x4c, 0x44, 0x0a, 0xe3, 0xca, 0x08, 0xc3, 0x99, 0xed, 0xf2, 0xd4, 0xbe,
0x3c, 0xa2, 0x52, 0x45, 0x42, 0x29, 0xd7, 0x80, 0x86, 0x92, 0x5f, 0x91, 0x92, 0xf7, 0x5c, 0x4d,
0x48, 0xb0, 0x48, 0x93, 0xad, 0x62, 0x2c, 0x64, 0xab, 0x18, 0xc6, 0xbf, 0xab, 0x42, 0x59, 0x76,
0x23, 0xea, 0x0b, 0xa1, 0x73, 0x41, 0x23, 0x7d, 0x81, 0x7d, 0x31, 0x35, 0xc4, 0xa7, 0x53, 0x2f,
0x54, 0x7a, 0x22, 0x5f, 0x26, 0x75, 0x0e, 0x14, 0x9a, 0xa2, 0xa6, 0xab, 0x70, 0x73, 0x2b, 0xe7,
0x7c, 0x52, 0x57, 0xe1, 0x92, 0xe8, 0x2d, 0x28, 0x4b, 0x8d, 0xa3, 0xa8, 0xac, 0x2d, 0x0b, 0x23,
0xae, 0x6e, 0x6c, 0x42, 0x65, 0x64, 0xcf, 0xec, 0x91, 0x13, 0x72, 0x65, 0xa1, 0x60, 0xaa, 0x6f,
0x96, 0xfb, 0xc4, 0x1b, 0xd9, 0x13, 0xeb, 0xc4, 0x9e, 0xd8, 0xee, 0x88, 0x0a, 0x3b, 0x66, 0x1d,
0x81, 0xdb, 0x1c, 0x46, 0xbe, 0x05, 0x8b, 0xa2, 0x9e, 0x92, 0x8a, 0x9b, 0x33, 0x45, 0xed, 0x25,
0x19, 0xd3, 0x69, 0xbd, 0x29, 0x1b, 0x97, 0x53, 0xca, 0xb5, 0xbf, 0x82, 0x59, 0xe5, 0x90, 0x3d,
0x8a, 0xad, 0x15, 0xe8, 0xe7, 0x7c, 0x0e, 0x57, 0x79, 0x51, 0x1c, 0xf8, 0x15, 0x9f, 0xbf, 0x69,
0x15, 0xb0, 0xa0, 0xa9, 0x80, 0xef, 0xc2, 0xf2, 0xdc, 0x0d, 0x68, 0x18, 0x4e, 0xe8, 0x58, 0xd5,
0xa5, 0x86, 0x44, 0x4d, 0x85, 0x90, 0xd5, 0xd9, 0x82, 0x15, 0x6e, 0x80, 0x0d, 0xec, 0xd0, 0x0b,
0xce, 0x9d, 0xc0, 0x0a, 0xa8, 0x2b, 0x0d, 0x71, 0xcb, 0x88, 0x1a, 0x08, 0xcc, 0x80, 0x1b, 0x6f,
0x36, 0x12, 0xf4, 0x3e, 0x1d, 0x51, 0xe7, 0x82, 0x8e, 0x51, 0x3d, 0x2c, 0x98, 0x6b, 0xb1, 0x34,
0xa6, 0x40, 0xa2, 0xae, 0x3f, 0x9f, 0x5a, 0xf3, 0xd9, 0xd8, 0x66, 0x6a, 0xc0, 0x22, 0xd7, 0xb7,
0xdc, 0xf9, 0xf4, 0x98, 0x43, 0xc8, 0x03, 0x90, 0xfa, 0x9f, 0x98, 0x33, 0x4b, 0xb1, 0xcd, 0x88,
0x71, 0x0d, 0xb3, 0x2e, 0x28, 0xb8, 0x7e, 0x7a, 0x47, 0x5f, 0x2c, 0x4d, 0x36, 0xc3, 0x70, 0xfb,
0x8f, 0x16, 0x4c, 0x0b, 0xca, 0x33, 0xdf, 0xb9, 0xb0, 0x43, 0xda, 0x5a, 0xe6, 0x7b, 0xbf, 0xf8,
0x64, 0x0c, 0xdc, 0x71, 0x9d, 0xd0, 0xb1, 0x43, 0xcf, 0x6f, 0x11, 0xc4, 0x45, 0x00, 0x72, 0x1f,
0x96, 0x71, 0x9e, 0x04, 0xa1, 0x1d, 0xce, 0x03, 0xa1, 0xfc, 0xae, 0x70, 0x25, 0x93, 0x21, 0x06,
0x08, 0x47, 0xfd, 0x97, 0x7c, 0x0a, 0xeb, 0x7c, 0x6a, 0xa4, 0x96, 0xe6, 0xaa, 0x12, 0x48, 0x56,
0x90, 0x62, 0x27, 0xbe, 0x46, 0x3f, 0x87, 0x0d, 0x31, 0x5d, 0x52, 0x29, 0xd7, 0x54, 0xca, 0x55,
0x4e, 0x92, 0x48, 0xba, 0x05, 0xcb, 0xac, 0x6a, 0xce, 0xc8, 0x12, 0x39, 0xb0, 0x55, 0xb1, 0xce,
0x5a, 0x81, 0x89, 0x96, 0x38, 0xd2, 0x44, 0xdc, 0x13, 0x7a, 0x45, 0xbe, 0x0b, 0x4b, 0x7c, 0xfa,
0xa0, 0x85, 0x07, 0xb7, 0xec, 0x4d, 0xdc, 0xb2, 0xd7, 0x44, 0xe7, 0xee, 0x28, 0x2c, 0xee, 0xda,
0x8b, 0xa3, 0xd8, 0x37, 0x5b, 0x1a, 0x13, 0xe7, 0x94, 0xb2, 0x7d, 0xa2, 0xb5, 0xc1, 0x27, 0x9b,
0xfc, 0x66, 0xab, 0x76, 0x3e, 0x43, 0x4c, 0x8b, 0x33, 0x6b, 0xfe, 0x85, 0xf3, 0x78, 0xe2, 0x05,
0x54, 0x9a, 0xee, 0x5b, 0x37, 0xc5, 0x82, 0x64, 0x40, 0xa9, 0xa9, 0xbd, 0x0d, 0x4b, 0xc2, 0xee,
0xa2, 0x0e, 0x58, 0x6e, 0xe1, 0xc4, 0x68, 0x70, 0xf3, 0x8b, 0x3c, 0x64, 0x61, 0x02, 0xe3, 0xb9,
0xfd, 0x5c, 0xb2, 0xf5, 0xd7, 0x90, 0x9b, 0x00, 0x03, 0x09, 0x86, 0xbe, 0x07, 0xcb, 0x62, 0x14,
0x22, 0x66, 0xda, 0xba, 0x8d, 0x5b, 0xe4, 0x4d, 0xd9, 0xc6, 0x14, 0xb7, 0x35, 0x9b, 0x7c, 0x5c,
0x34, 0xfe, 0xbb, 0x0f, 0x44, 0x0e, 0x8a, 0x96, 0xd1, 0xeb, 0x2f, 0xcb, 0x68, 0x59, 0x0c, 0x53,
0x04, 0x32, 0x7e, 0x3f, 0xc7, 0x65, 0x2d, 0x41, 0x1d, 0x68, 0x36, 0x2f, 0xce, 0xd7, 0x2c, 0xcf,
0x9d, 0x5c, 0x09, 0x56, 0x07, 0x1c, 0xd4, 0x77, 0x27, 0xc8, 0x6b, 0x1c, 0x57, 0x27, 0xe1, 0x9b,
0x77, 0x5d, 0x02, 0x91, 0xe8, 0x0e, 0xd4, 0x66, 0xf3, 0x93, 0x89, 0x33, 0xe2, 0x24, 0x05, 0x9e,
0x0b, 0x07, 0x21, 0xc1, 0x1b, 0x50, 0x17, 0x73, 0x9d, 0x53, 0x70, 0x65, 0xb1, 0x26, 0x60, 0x48,
0x82, 0xc2, 0x01, 0xf5, 0x91, 0xd9, 0xd5, 0x4d, 0xfc, 0x6d, 0x6c, 0xc3, 0x6a, 0xbc, 0xd2, 0x42,
0x72, 0xb9, 0x0f, 0x15, 0xc1, 0x49, 0xa5, 0xc1, 0x78, 0x31, 0xde, 0x1b, 0xa6, 0xc2, 0x1b, 0xff,
0xbe, 0x04, 0x2b, 0xb2, 0x8f, 0xd8, 0x60, 0x0f, 0xe6, 0xd3, 0xa9, 0xed, 0x67, 0xb0, 0xe8, 0xdc,
0x8b, 0x59, 0x74, 0x3e, 0xc5, 0xa2, 0xe3, 0xe6, 0x40, 0xce, 0xe1, 0xe3, 0xe6, 0x40, 0x36, 0xbb,
0xb8, 0x11, 0x42, 0x3f, 0xb1, 0x6a, 0x08, 0xf0, 0x90, 0x9f, 0x8c, 0xa5, 0x36, 0x94, 0x52, 0xc6,
0x86, 0xa2, 0x6f, 0x07, 0x0b, 0x89, 0xed, 0xe0, 0x0d, 0xe0, 0xd3, 0x58, 0xce, 0xc7, 0x32, 0xb7,
0x4b, 0x20, 0x4c, 0x4c, 0xc8, 0x77, 0x60, 0x29, 0xc9, 0x81, 0x39, 0xab, 0x5f, 0xcc, 0xe0, 0xbf,
0xce, 0x94, 0xa2, 0x50, 0xa3, 0x11, 0x57, 0x05, 0xff, 0x75, 0xa6, 0xf4, 0x00, 0x31, 0x92, 0xbe,
0x03, 0xc0, 0xcb, 0xc6, 0x65, 0x0c, 0xb8, 0x8c, 0xdf, 0x4e, 0xcc, 0x4c, 0xad, 0xd7, 0xb7, 0xd8,
0xc7, 0xdc, 0xa7, 0xb8, 0xae, 0xab, 0x98, 0x12, 0x97, 0xf4, 0xa7, 0xb0, 0xe8, 0xcd, 0xa8, 0x6b,
0x45, 0x5c, 0xb0, 0x86, 0x59, 0x35, 0x45, 0x56, 0x5d, 0x09, 0x37, 0x1b, 0x8c, 0x4e, 0x7d, 0x92,
0xcf, 0x79, 0x27, 0x53, 0x2d, 0x65, 0xfd, 0x9a, 0x94, 0x8b, 0x48, 0x18, 0x25, 0xfd, 0x08, 0x4d,
0x6e, 0xde, 0x64, 0xce, 0x0f, 0xb9, 0x1a, 0x38, 0x8f, 0xa4, 0xd5, 0xdf, 0x54, 0x18, 0x53, 0xa7,
0x32, 0x7e, 0x23, 0x07, 0x35, 0xad, 0x0d, 0x64, 0x0d, 0x96, 0x77, 0xfa, 0xfd, 0xa3, 0x8e, 0xd9,
0x1e, 0x76, 0xbf, 0xec, 0x58, 0x3b, 0x07, 0xfd, 0x41, 0xa7, 0x79, 0x83, 0x81, 0x0f, 0xfa, 0x3b,
0xed, 0x03, 0x6b, 0xaf, 0x6f, 0xee, 0x48, 0x70, 0x8e, 0xac, 0x03, 0x31, 0x3b, 0x87, 0xfd, 0x61,
0x27, 0x06, 0xcf, 0x93, 0x26, 0xd4, 0xb7, 0xcd, 0x4e, 0x7b, 0x67, 0x5f, 0x40, 0x0a, 0x64, 0x15,
0x9a, 0x7b, 0xc7, 0xbd, 0xdd, 0x6e, 0xef, 0xb1, 0xb5, 0xd3, 0xee, 0xed, 0x74, 0x0e, 0x3a, 0xbb,
0xcd, 0x22, 0x69, 0x40, 0xb5, 0xbd, 0xdd, 0xee, 0xed, 0xf6, 0x7b, 0x9d, 0xdd, 0x66, 0xc9, 0xf8,
0x93, 0x1c, 0x40, 0x54, 0x51, 0xc6, 0x57, 0xa3, 0xaa, 0xea, 0xc7, 0xcd, 0x6b, 0xa9, 0x46, 0x71,
0xbe, 0xea, 0xc7, 0xbe, 0xc9, 0x43, 0x28, 0x7b, 0xf3, 0x70, 0xe4, 0x4d, 0xb9, 0x12, 0xb1, 0xf8,
0xb0, 0x95, 0x4a, 0xd7, 0xe7, 0x78, 0x53, 0x12, 0xc6, 0x8e, 0x94, 0x0b, 0x2f, 0x3b, 0x52, 0x8e,
0x9f, 0x5d, 0x73, 0xb9, 0x4e, 0x3b, 0xbb, 0xbe, 0x0d, 0x10, 0x3c, 0xa7, 0x74, 0x86, 0x36, 0x3b,
0xb1, 0x0a, 0xaa, 0x08, 0x19, 0x32, 0xbd, 0xf4, 0x3f, 0xe5, 0x60, 0x0d, 0xe7, 0xd2, 0x38, 0xc9,
0xc4, 0xee, 0x42, 0x6d, 0xe4, 0x79, 0x33, 0xca, 0x84, 0x6a, 0x25, 0xaf, 0xe9, 0x20, 0xc6, 0xa0,
0x38, 0x43, 0x3e, 0xf5, 0xfc, 0x11, 0x15, 0x3c, 0x0c, 0x10, 0xb4, 0xc7, 0x20, 0x6c, 0x0d, 0x89,
0x45, 0xc8, 0x29, 0x38, 0x0b, 0xab, 0x71, 0x18, 0x27, 0x59, 0x87, 0x85, 0x13, 0x9f, 0xda, 0xa3,
0x73, 0xc1, 0xbd, 0xc4, 0x17, 0xf9, 0x76, 0x64, 0xbb, 0x1c, 0xb1, 0x35, 0x31, 0xa1, 0xbc, 0xf2,
0x15, 0x73, 0x49, 0xc0, 0x77, 0x04, 0x98, 0xed, 0xf3, 0xf6, 0x89, 0xed, 0x8e, 0x3d, 0x97, 0x8e,
0x85, 0xfe, 0x1f, 0x01, 0x8c, 0x23, 0x58, 0x4f, 0xb6, 0x4f, 0xf0, 0xbb, 0x4f, 0x34, 0x7e, 0xc7,
0x95, 0xe2, 0xcd, 0xeb, 0xd7, 0x98, 0xc6, 0xfb, 0xfe, 0x73, 0x11, 0x8a, 0x4c, 0xe1, 0xb9, 0x56,
0x37, 0xd2, 0x75, 0xdb, 0x42, 0xca, 0xd1, 0x00, 0x4d, 0xa4, 0x5c, 0x00, 0x13, 0x83, 0x85, 0x10,
0x14, 0xbc, 0x14, 0xda, 0xa7, 0xa3, 0x0b, 0xa9, 0xb3, 0x20, 0xc4, 0xa4, 0xa3, 0x0b, 0x34, 0x74,
0xd8, 0x21, 0x4f, 0xcb, 0xf9, 0x55, 0x39, 0xb0, 0x43, 0x4c, 0x29, 0x50, 0x98, 0xae, 0xac, 0x50,
0x98, 0xaa, 0x05, 0x65, 0xc7, 0x3d, 0xf1, 0xe6, 0xae, 0x34, 0x2b, 0xc9, 0x4f, 0xf4, 0x6b, 0x40,
0x4e, 0xca, 0xb6, 0x76, 0xce, 0x8d, 0x2a, 0x0c, 0x30, 0x64, 0x9b, 0xfb, 0x87, 0x50, 0x0d, 0xae,
0xdc, 0x91, 0xce, 0x83, 0x56, 0x45, 0xff, 0xb0, 0xd6, 0x6f, 0x0d, 0xae, 0xdc, 0x11, 0xce, 0xf8,
0x4a, 0x20, 0x7e, 0x91, 0x47, 0x50, 0x51, 0xe7, 0x7d, 0x7c, 0x07, 0xb9, 0xa9, 0xa7, 0x90, 0x87,
0x7c, 0xdc, 0x46, 0xa7, 0x48, 0xc9, 0x07, 0xb0, 0x80, 0x76, 0xff, 0xa0, 0x55, 0xc7, 0x44, 0x52,
0xe1, 0x65, 0xd5, 0x40, 0x97, 0x02, 0x3a, 0xc6, 0xd3, 0x37, 0x53, 0x90, 0xb1, 0x6e, 0x3a, 0x9d,
0xd8, 0x33, 0x61, 0x85, 0x6f, 0xf0, 0x93, 0x79, 0x06, 0xe1, 0x26, 0xf8, 0xbb, 0x50, 0xc7, 0xb3,
0x54, 0xa4, 0x71, 0xb9, 0x1c, 0x5a, 0x30, 0x81, 0xc1, 0xf6, 0x26, 0xf6, 0xac, 0x17, 0x6c, 0x3e,
0x81, 0x46, 0xac, 0x32, 0xba, 0x09, 0xad, 0xc1, 0x4d, 0x68, 0x6f, 0xe9, 0x26, 0xb4, 0x68, 0x2b,
0x14, 0xc9, 0x74, 0x93, 0xda, 0x11, 0x54, 0x64, 0x5f, 0x30, 0x9e, 0x73, 0xdc, 0x7b, 0xd2, 0xeb,
0x7f, 0xd5, 0xb3, 0x06, 0x4f, 0x7b, 0x3b, 0xcd, 0x1b, 0x64, 0x09, 0x6a, 0xed, 0x1d, 0x64, 0x63,
0x08, 0xc8, 0x31, 0x92, 0xa3, 0xf6, 0x60, 0xa0, 0x20, 0x79, 0x46, 0x72, 0xd4, 0xed, 0xf5, 0x3a,
0xbb, 0x1c, 0x50, 0x30, 0xf6, 0xa0, 0x99, 0x6c, 0x3b, 0x9b, 0xe5, 0xa1, 0x84, 0x89, 0x13, 0xce,
0x08, 0x10, 0x9d, 0xa3, 0xe4, 0xb5, 0x73, 0x14, 0xe3, 0x11, 0x34, 0xd9, 0x4e, 0xcf, 0x3a, 0x5f,
0x77, 0x7c, 0x98, 0x30, 0x59, 0x5c, 0x3f, 0xe5, 0xac, 0x98, 0x35, 0x0e, 0xc3, 0xa2, 0x8c, 0x4f,
0x60, 0x59, 0x4b, 0x16, 0xd9, 0x8f, 0x98, 0xf4, 0x90, 0xb4, 0x1f, 0xa1, 0xe6, 0xcf, 0x31, 0xc6,
0x06, 0xac, 0xb1, 0xcf, 0xce, 0x05, 0x75, 0xc3, 0xc1, 0xfc, 0x84, 0xfb, 0xcb, 0x38, 0x9e, 0x6b,
0xfc, 0x6a, 0x0e, 0xaa, 0x0a, 0x73, 0xfd, 0xb2, 0xd9, 0x12, 0xa6, 0x26, 0xce, 0x27, 0x37, 0xb5,
0x12, 0x30, 0xe1, 0x16, 0xfe, 0x8d, 0x4c, 0x4e, 0xc6, 0x16, 0x54, 0x15, 0x08, 0x3b, 0xb1, 0xd3,
0x31, 0xad, 0x7e, 0xef, 0xa0, 0xdb, 0x63, 0xbb, 0x05, 0xeb, 0x67, 0x04, 0xec, 0xed, 0x21, 0x24,
0x67, 0x34, 0x61, 0xf1, 0x31, 0x0d, 0xbb, 0xee, 0xa9, 0x27, 0x3a, 0xc3, 0xf8, 0xf5, 0x05, 0x58,
0x52, 0xa0, 0xc8, 0x30, 0x75, 0x41, 0xfd, 0xc0, 0xf1, 0x5c, 0x9c, 0x38, 0x55, 0x53, 0x7e, 0x32,
0x7e, 0x27, 0xd4, 0x36, 0x94, 0x3b, 0x56, 0x11, 0x2b, 0x14, 0x3d, 0x14, 0x3a, 0xde, 0x81, 0x25,
0x67, 0x4c, 0xdd, 0xd0, 0x09, 0xaf, 0xac, 0xd8, 0xe9, 0xc4, 0xa2, 0x04, 0x0b, 0xc1, 0x63, 0x15,
0x4a, 0xf6, 0xc4, 0xb1, 0xa5, 0x1f, 0x12, 0xff, 0x60, 0xd0, 0x91, 0x37, 0xf1, 0x7c, 0x54, 0x64,
0xaa, 0x26, 0xff, 0x20, 0x0f, 0x60, 0x95, 0x29, 0x55, 0xfa, 0x71, 0x1a, 0xb2, 0x2c, 0x7e, 0x50,
0x42, 0xdc, 0xf9, 0xf4, 0x28, 0x3a, 0x52, 0x63, 0x18, 0x26, 0x6e, 0xb0, 0x14, 0x42, 0xbe, 0x54,
0x09, 0xb8, 0xa1, 0x64, 0xd9, 0x9d, 0x4f, 0xdb, 0x88, 0x51, 0xf4, 0x0f, 0x61, 0x8d, 0xd1, 0x2b,
0x89, 0x54, 0xa5, 0x58, 0xc2, 0x14, 0x2c, 0xb3, 0xae, 0xc0, 0xa9, 0x34, 0xb7, 0xa0, 0xca, 0x6b,
0xc5, 0xa6, 0x84, 0x38, 0x77, 0xc3, 0xaa, 0x50, 0x3f, 0x48, 0xb9, 0x0c, 0x71, 0xcb, 0x40, 0xd2,
0x65, 0x48, 0x73, 0x3a, 0xaa, 0x24, 0x9d, 0x8e, 0x1e, 0xc2, 0xda, 0x09, 0x9b, 0xa3, 0xe7, 0xd4,
0x1e, 0x53, 0xdf, 0x8a, 0x66, 0x3e, 0xd7, 0x3f, 0x57, 0x18, 0x72, 0x1f, 0x71, 0x6a, 0xa1, 0x30,
0xd1, 0x90, 0x71, 0x22, 0x3a, 0xb6, 0x42, 0xcf, 0x42, 0x89, 0x51, 0x98, 0x6d, 0x1b, 0x1c, 0x3c,
0xf4, 0x76, 0x18, 0x30, 0x4e, 0x77, 0xe6, 0xdb, 0xb3, 0x73, 0xa1, 0x1d, 0x2a, 0xba, 0xc7, 0x0c,
0x48, 0x5e, 0x83, 0x32, 0x5b, 0x13, 0x2e, 0xe5, 0x7e, 0x16, 0x5c, 0xef, 0x92, 0x20, 0xf2, 0x16,
0x2c, 0x60, 0x19, 0x41, 0xab, 0x89, 0x0b, 0xa2, 0x1e, 0xed, 0x1d, 0x8e, 0x6b, 0x0a, 0x1c, 0x93,
0xbf, 0xe7, 0xbe, 0xc3, 0x19, 0x5b, 0xd5, 0xc4, 0xdf, 0xe4, 0x7b, 0x1a, 0x97, 0x5c, 0xc1, 0xb4,
0x6f, 0x89, 0xb4, 0x89, 0xa9, 0x78, 0x1d, 0xc3, 0xfc, 0x46, 0xd9, 0xd7, 0xf7, 0x8b, 0x95, 0x5a,
0xb3, 0x6e, 0xb4, 0xd0, 0x53, 0xca, 0xa4, 0x23, 0xef, 0x82, 0xfa, 0x57, 0xb1, 0x35, 0x92, 0x83,
0x8d, 0x14, 0x2a, 0xf2, 0x99, 0xf0, 0x05, 0xdc, 0x9a, 0x7a, 0x63, 0x29, 0x25, 0xd4, 0x25, 0xf0,
0xd0, 0x1b, 0x33, 0x69, 0x66, 0x59, 0x11, 0x9d, 0x3a, 0xae, 0x13, 0x9c, 0xd3, 0xb1, 0x10, 0x16,
0x9a, 0x12, 0xb1, 0x27, 0xe0, 0x4c, 0x24, 0x9f, 0xf9, 0xde, 0x99, 0xda, 0x3b, 0x73, 0xa6, 0xfa,
0x36, 0x3e, 0x85, 0x12, 0x1f, 0x41, 0xb6, 0x50, 0x70, 0x7c, 0x73, 0x62, 0xa1, 0x20, 0xb4, 0x05,
0x65, 0x97, 0x86, 0xcf, 0x3d, 0xff, 0x99, 0xb4, 0x40, 0x8b, 0x4f, 0xe3, 0x47, 0x68, 0x65, 0x55,
0x2e, 0x6f, 0xdc, 0x1a, 0xc1, 0xa6, 0x30, 0x9f, 0x82, 0xc1, 0xb9, 0x2d, 0x0c, 0xbf, 0x15, 0x04,
0x0c, 0xce, 0xed, 0xd4, 0x14, 0xce, 0xa7, 0xbd, 0xde, 0xde, 0x82, 0x45, 0xe9, 0x64, 0x17, 0x58,
0x13, 0x7a, 0x1a, 0x8a, 0x25, 0x59, 0x17, 0x1e, 0x76, 0xc1, 0x01, 0x3d, 0x0d, 0x8d, 0x43, 0x58,
0x16, 0x8b, 0xa6, 0x3f, 0xa3, 0xb2, 0xe8, 0xcf, 0xb2, 0xd4, 0xa4, 0xda, 0xc3, 0x95, 0xb8, 0xfc,
0xc1, 0x25, 0xbd, 0x98, 0xee, 0x64, 0xfc, 0x20, 0x32, 0x29, 0x32, 0xe9, 0x44, 0xe4, 0x27, 0x94,
0x15, 0x79, 0x34, 0x2b, 0xdd, 0x3f, 0x94, 0x4a, 0xe4, 0x8c, 0x59, 0xef, 0x04, 0xf3, 0xd1, 0x48,
0x3a, 0x3f, 0x56, 0x4c, 0xf9, 0x69, 0xfc, 0xaf, 0x1c, 0xac, 0x60, 0x66, 0x52, 0xcd, 0x13, 0x3b,
0xc5, 0x8f, 0x5d, 0x49, 0x36, 0x3e, 0xba, 0x48, 0xc8, 0x3f, 0x5e, 0x7e, 0x22, 0x94, 0x3c, 0xed,
0x29, 0x66, 0x9e, 0xf6, 0x7c, 0x1b, 0x9a, 0x63, 0x3a, 0x71, 0x70, 0x3a, 0x49, 0x29, 0x8b, 0x8b,
0xb5, 0x4b, 0x12, 0x2e, 0x4d, 0x0f, 0xa9, 0x23, 0xa6, 0x85, 0xf4, 0xf1, 0xe3, 0xdf, 0xcc, 0xc1,
0x32, 0x17, 0xf4, 0xd0, 0xe0, 0x23, 0x3a, 0xf4, 0x0b, 0x69, 0xd9, 0x10, 0x6c, 0x57, 0xb4, 0x3d,
0x12, 0x80, 0x10, 0xca, 0x89, 0xf7, 0x6f, 0x08, 0x8b, 0x87, 0x80, 0x92, 0xef, 0xa0, 0x0a, 0xeb,
0x5a, 0x08, 0x14, 0x02, 0xfc, 0xcd, 0x0c, 0xd1, 0x52, 0x25, 0x67, 0xfa, 0xad, 0x8b, 0xa0, 0xed,
0x0a, 0x2c, 0x70, 0xf3, 0x99, 0xb1, 0x07, 0x8d, 0x58, 0x31, 0xb1, 0x63, 0xa5, 0x3a, 0x3f, 0x56,
0x4a, 0x9d, 0x9e, 0xe7, 0xd3, 0xa7, 0xe7, 0x57, 0xb0, 0x62, 0x52, 0x7b, 0x7c, 0xb5, 0xe7, 0xf9,
0x47, 0xc1, 0x49, 0xb8, 0xc7, 0xa5, 0x67, 0xb6, 0x57, 0x29, 0x7f, 0x99, 0xd8, 0x39, 0x8c, 0xf4,
0x0c, 0x90, 0x9d, 0xf8, 0x2d, 0x58, 0x8c, 0x1c, 0x6b, 0x34, 0x8b, 0x7d, 0x43, 0xf9, 0xd6, 0xa0,
0xd0, 0x45, 0xa0, 0x38, 0x0b, 0x4e, 0x42, 0x61, 0xb3, 0xc7, 0xdf, 0xc6, 0x3f, 0x2f, 0x01, 0x61,
0xb3, 0x3e, 0x31, 0xb1, 0x52, 0xc3, 0x92, 0x4b, 0x9f, 0xfc, 0x25, 0xdc, 0x86, 0xf2, 0x29, 0xb7,
0xa1, 0x07, 0x40, 0x34, 0x02, 0xe9, 0xcd, 0x54, 0x50, 0xde, 0x4c, 0xcd, 0x88, 0x56, 0x38, 0x33,
0x3d, 0x80, 0x55, 0xa1, 0xae, 0xc4, 0x9b, 0x83, 0xd3, 0xcc, 0x24, 0x5c, 0x6f, 0x89, 0xb5, 0x49,
0xba, 0x0c, 0x49, 0x33, 0x78, 0x81, 0xbb, 0x0c, 0x49, 0x6b, 0x95, 0x36, 0x99, 0x17, 0x5e, 0x3a,
0x99, 0xcb, 0x99, 0x93, 0x59, 0xb3, 0x5e, 0x56, 0xe2, 0xd6, 0xcb, 0x94, 0x1d, 0x9e, 0xcb, 0xe7,
0x31, 0x3b, 0xfc, 0x3d, 0x68, 0x4a, 0x4b, 0x96, 0xb2, 0x91, 0x0a, 0x5f, 0x12, 0x61, 0xac, 0x92,
0x56, 0xd2, 0xd8, 0x41, 0x63, 0xed, 0x55, 0x4e, 0x3c, 0xeb, 0xd9, 0x27, 0x9e, 0x69, 0x9b, 0x5f,
0x23, 0xc3, 0xe6, 0xf7, 0x28, 0x72, 0x15, 0x09, 0xce, 0x9d, 0x29, 0x0a, 0x52, 0x91, 0xaf, 0xab,
0xe8, 0xe4, 0xc1, 0xb9, 0x33, 0x35, 0xa5, 0xd3, 0x16, 0xfb, 0x20, 0x3b, 0x70, 0x47, 0xb4, 0x27,
0xc3, 0xdf, 0x8a, 0xf7, 0xc2, 0x12, 0x4e, 0x95, 0x4d, 0x4e, 0x76, 0x98, 0x70, 0xbd, 0x4a, 0x74,
0x8a, 0xf4, 0xd6, 0x09, 0xb8, 0xe1, 0x58, 0x76, 0xca, 0x21, 0x77, 0xd7, 0x41, 0xf6, 0xc0, 0x48,
0x84, 0x51, 0x31, 0xb8, 0x40, 0xb9, 0xab, 0x61, 0xd6, 0xa6, 0xf6, 0xe5, 0x01, 0x1a, 0x0d, 0x83,
0x0b, 0xe3, 0xcf, 0x73, 0xd0, 0x64, 0x53, 0x38, 0xc6, 0x1d, 0x3e, 0x07, 0xe4, 0x77, 0xaf, 0xc8,
0x1c, 0x6a, 0x8c, 0x56, 0xf2, 0x86, 0x4f, 0x01, 0x17, 0xbb, 0xe5, 0xcd, 0xa8, 0x2b, 0x58, 0x43,
0x2b, 0xce, 0x1a, 0xa2, 0x6d, 0x62, 0xff, 0x06, 0xd7, 0x3a, 0x19, 0x84, 0x7c, 0x0e, 0x55, 0xb6,
0xa6, 0x70, 0xf2, 0x0a, 0x3f, 0xf3, 0x4d, 0x65, 0x49, 0x48, 0x2d, 0x6f, 0x96, 0x74, 0x26, 0x3e,
0xb3, 0x9c, 0xb1, 0x8a, 0x19, 0xce, 0x58, 0x1a, 0xef, 0xd9, 0x07, 0x78, 0x42, 0xaf, 0x58, 0x27,
0x84, 0x9e, 0xcf, 0x64, 0x35, 0xb6, 0xc4, 0x4e, 0xed, 0xa9, 0x23, 0xac, 0x99, 0x25, 0xb3, 0xfa,
0x8c, 0x5e, 0xed, 0x21, 0x80, 0xcd, 0x2d, 0x86, 0x8e, 0x18, 0x50, 0xc9, 0xac, 0x3c, 0xa3, 0x57,
0x9c, 0xfb, 0x58, 0xd0, 0x78, 0x42, 0xaf, 0x76, 0x29, 0x57, 0x06, 0x3c, 0x9f, 0x75, 0xba, 0x6f,
0x3f, 0x67, 0xd2, 0x7f, 0xcc, 0x59, 0xa8, 0xe6, 0xdb, 0xcf, 0x9f, 0xd0, 0x2b, 0xe9, 0xb8, 0x54,
0x66, 0xf8, 0x89, 0x37, 0x12, 0xe2, 0x8b, 0x34, 0x20, 0x45, 0x95, 0x32, 0x17, 0x9e, 0xe1, 0x6f,
0xe3, 0xcf, 0x72, 0xd0, 0x60, 0xf5, 0xc7, 0x9d, 0x07, 0x67, 0x91, 0xf0, 0x3e, 0xce, 0x45, 0xde,
0xc7, 0x0f, 0x05, 0x43, 0xe6, 0xdb, 0x58, 0xfe, 0xfa, 0x6d, 0x0c, 0xc7, 0x86, 0xef, 0x61, 0x1f,
0x42, 0x95, 0x4f, 0x0c, 0xc6, 0x7e, 0x0a, 0xb1, 0x01, 0x8e, 0x35, 0xc8, 0xac, 0x20, 0xd9, 0x13,
0xee, 0xc9, 0xa8, 0xd9, 0xea, 0x79, 0x17, 0x57, 0x7d, 0x65, 0xa1, 0xcf, 0x18, 0x86, 0xd2, 0x35,
0x9e, 0x8c, 0xba, 0x21, 0x7c, 0x21, 0x69, 0x08, 0x37, 0x5c, 0xa8, 0xb0, 0xa1, 0xc6, 0xc6, 0x66,
0x64, 0x9a, 0xcb, 0xca, 0x94, 0x09, 0x3b, 0x36, 0xdb, 0xcf, 0x18, 0x8f, 0xce, 0x0b, 0x61, 0xc7,
0x0e, 0x28, 0xcb, 0x88, 0x55, 0xdc, 0xf5, 0x2c, 0xb4, 0x2c, 0x0b, 0x9b, 0x6b, 0xc5, 0xac, 0xba,
0xde, 0x11, 0x07, 0x18, 0x7f, 0x25, 0x07, 0x35, 0x6d, 0xcd, 0xe2, 0x51, 0x83, 0xea, 0x4e, 0xbe,
0xc0, 0xe3, 0x2b, 0x20, 0x36, 0x1e, 0xfb, 0x37, 0xcc, 0xc6, 0x28, 0x36, 0x40, 0x5b, 0x62, 0x2a,
0x63, 0xca, 0x7c, 0xcc, 0xbe, 0x25, 0xdb, 0x25, 0xe7, 0x2f, 0xfb, 0xbd, 0xbd, 0x00, 0x45, 0x46,
0x6a, 0x7c, 0x01, 0xcb, 0x5a, 0x35, 0xb8, 0xfd, 0xe7, 0x55, 0x3b, 0xc0, 0xf8, 0x05, 0x95, 0x98,
0x95, 0xc1, 0xcf, 0xee, 0xa5, 0xd3, 0x28, 0x1d, 0xf3, 0x7e, 0x11, 0xce, 0xa9, 0x1c, 0x84, 0x3d,
0xf3, 0x8a, 0x7e, 0x8c, 0xc6, 0xaf, 0xe4, 0x60, 0x45, 0xcb, 0x7e, 0xcf, 0x71, 0xed, 0x89, 0xf3,
0x23, 0xdc, 0xc6, 0x02, 0xe7, 0xcc, 0x4d, 0x14, 0xc0, 0x41, 0x5f, 0xa7, 0x00, 0x72, 0x17, 0xea,
0xdc, 0x4b, 0x9d, 0xdf, 0x81, 0x10, 0xdb, 0x2c, 0x20, 0xcc, 0xb4, 0x9f, 0x0f, 0x2f, 0x8d, 0xbf,
0x95, 0x87, 0x55, 0x51, 0x05, 0xbc, 0x4c, 0xe0, 0x30, 0x51, 0xf7, 0x30, 0x38, 0x23, 0x9f, 0x43,
0x83, 0x75, 0x9f, 0xe5, 0xd3, 0x33, 0x27, 0x08, 0xa9, 0x74, 0x2b, 0xc8, 0xe0, 0xc6, 0x4c, 0x92,
0x61, 0xa4, 0xa6, 0xa0, 0x24, 0x5f, 0x40, 0x0d, 0x93, 0x72, 0x13, 0x9c, 0x18, 0xab, 0x56, 0x3a,
0x21, 0x1f, 0x8b, 0xfd, 0x1b, 0x26, 0x04, 0xd1, 0xc8, 0x7c, 0x01, 0x35, 0x1c, 0xe6, 0x0b, 0xec,
0xeb, 0x04, 0xb3, 0x4b, 0x8d, 0x05, 0x4b, 0x3c, 0x8b, 0x46, 0xa6, 0x0d, 0x0d, 0xce, 0xee, 0x44,
0x4f, 0x0a, 0x0f, 0xe4, 0xcd, 0x74, 0x72, 0xd9, 0xd7, 0xac, 0xf2, 0x33, 0xed, 0x7b, 0xbb, 0x0a,
0xe5, 0xd0, 0x77, 0xce, 0xce, 0xa8, 0x6f, 0xac, 0xab, 0xae, 0x61, 0x7c, 0x9c, 0x0e, 0x42, 0x3a,
0x63, 0x3a, 0x8c, 0xf1, 0xaf, 0x72, 0x50, 0x13, 0x9c, 0xf9, 0xc7, 0xf6, 0x58, 0xd8, 0x4c, 0x18,
0x6b, 0xab, 0x9a, 0x6d, 0xf6, 0x1d, 0x58, 0x9a, 0x32, 0x85, 0xcb, 0x09, 0xaf, 0xe2, 0xee, 0x0a,
0x8b, 0x12, 0x2c, 0x74, 0x89, 0x2d, 0x58, 0x41, 0xd5, 0x22, 0xb0, 0x42, 0x67, 0x62, 0x49, 0xa4,
0xb8, 0x6b, 0xb3, 0xcc, 0x51, 0x43, 0x67, 0x72, 0x28, 0x10, 0x4c, 0xc2, 0x0e, 0x42, 0xfb, 0x8c,
0x0a, 0xee, 0xc0, 0x3f, 0x98, 0x12, 0x97, 0xb0, 0x05, 0x48, 0x25, 0xee, 0xff, 0x2c, 0xc3, 0x46,
0x0a, 0x25, 0x94, 0x38, 0x75, 0x3a, 0x3c, 0x71, 0xa6, 0x27, 0x9e, 0x3a, 0x9d, 0xc8, 0x69, 0xa7,
0xc3, 0x07, 0x0c, 0x23, 0x4f, 0x27, 0x28, 0xac, 0xc9, 0x29, 0x8b, 0xc7, 0x0b, 0xca, 0x5c, 0x90,
0x47, 0x65, 0xf6, 0xc3, 0xf8, 0x36, 0x98, 0x2c, 0x4e, 0xc2, 0x75, 0xb9, 0x70, 0x65, 0x96, 0x82,
0x05, 0xe4, 0xff, 0x87, 0x96, 0x5a, 0x19, 0x42, 0xb7, 0xd1, 0x6c, 0x1f, 0xac, 0xa4, 0xf7, 0x5e,
0x52, 0x52, 0xcc, 0xee, 0x8b, 0xa2, 0xd7, 0xba, 0x5c, 0x54, 0x3c, 0x43, 0x55, 0xd6, 0x05, 0xbc,
0x2e, 0xcb, 0x42, 0x5d, 0x25, 0x5d, 0x62, 0xf1, 0x95, 0xda, 0x86, 0x36, 0xed, 0x58, 0xb1, 0xe6,
0x2d, 0x91, 0xb1, 0x42, 0xe9, 0xe5, 0x9e, 0xc3, 0xfa, 0x73, 0xdb, 0x09, 0x65, 0x1b, 0x35, 0xd3,
0x4b, 0x09, 0xcb, 0x7b, 0xf8, 0x92, 0xf2, 0xbe, 0xe2, 0x89, 0x63, 0xda, 0xdb, 0xea, 0xf3, 0x34,
0x30, 0xd8, 0xfc, 0xfb, 0x05, 0x58, 0x8c, 0xe7, 0xc2, 0x58, 0x8f, 0xd8, 0xae, 0xa4, 0x20, 0x2d,
0x34, 0x00, 0x71, 0x72, 0xd6, 0xe3, 0x02, 0x74, 0xfa, 0x4c, 0x2f, 0x9f, 0x71, 0xa6, 0xa7, 0x1f,
0xa5, 0x15, 0x5e, 0xe6, 0x59, 0x51, 0x7c, 0x25, 0xcf, 0x8a, 0x52, 0x96, 0x67, 0xc5, 0x47, 0xd7,
0x1e, 0xc5, 0x73, 0x83, 0x78, 0xe6, 0x31, 0xfc, 0xa3, 0xeb, 0x8f, 0xe1, 0xb9, 0xad, 0xfc, 0xba,
0x23, 0x78, 0xcd, 0x81, 0xa0, 0x72, 0xcd, 0x01, 0x98, 0xe6, 0x52, 0x90, 0x71, 0x04, 0x5f, 0xfd,
0x1a, 0x47, 0xf0, 0x9b, 0x7f, 0x96, 0x03, 0x92, 0x5e, 0x1d, 0xe4, 0x31, 0x3f, 0x2e, 0x75, 0xe9,
0x44, 0x70, 0xee, 0xf7, 0x5f, 0x6d, 0x85, 0xc9, 0x09, 0x21, 0x53, 0x93, 0x0f, 0x60, 0x45, 0xbf,
0x11, 0xa8, 0x9b, 0x36, 0x1a, 0x26, 0xd1, 0x51, 0x91, 0x91, 0x4e, 0x73, 0x63, 0x29, 0xbe, 0xd4,
0x8d, 0xa5, 0xf4, 0x52, 0x37, 0x96, 0x85, 0xb8, 0x1b, 0xcb, 0xe6, 0xbf, 0xc9, 0xc1, 0x4a, 0xc6,
0x24, 0xfe, 0xe6, 0xda, 0xcc, 0xe6, 0x5e, 0x8c, 0xad, 0xe5, 0xc5, 0xdc, 0xd3, 0x39, 0xda, 0x81,
0x34, 0xec, 0xb2, 0xa1, 0x08, 0xc4, 0x4e, 0x75, 0xff, 0x65, 0xdc, 0x25, 0x4a, 0x61, 0xea, 0xc9,
0x37, 0xff, 0x41, 0x1e, 0x6a, 0x1a, 0x92, 0xf5, 0x22, 0x9f, 0xb2, 0x9a, 0x53, 0x28, 0x97, 0x2d,
0xd1, 0x30, 0x83, 0x97, 0x14, 0x70, 0x72, 0x22, 0x9e, 0x2f, 0x2e, 0x21, 0x48, 0x22, 0xc1, 0x16,
0xac, 0xc8, 0xa3, 0x6c, 0x1a, 0xb9, 0xdf, 0x8b, 0xbd, 0x46, 0x78, 0x25, 0x88, 0x4a, 0x22, 0xfd,
0x07, 0x52, 0xcf, 0x8d, 0xc6, 0x4e, 0x3b, 0x1a, 0x5c, 0x16, 0xfe, 0x10, 0x62, 0x10, 0xd9, 0x3c,
0xff, 0x10, 0xd6, 0x94, 0x43, 0x44, 0x2c, 0x05, 0x3f, 0x80, 0x22, 0xd2, 0xf1, 0x41, 0x4b, 0xf2,
0x3d, 0xb8, 0x9d, 0xa8, 0x53, 0x22, 0x29, 0xb7, 0xb4, 0xdc, 0x8c, 0xd5, 0x4e, 0xcf, 0x61, 0xf3,
0x2f, 0x41, 0x23, 0xc6, 0x28, 0xbf, 0xb9, 0x21, 0x4f, 0x1a, 0xc3, 0x78, 0x8f, 0xea, 0xc6, 0xb0,
0xcd, 0xff, 0x59, 0x00, 0x92, 0xe6, 0xd5, 0x3f, 0xcd, 0x2a, 0xa4, 0x27, 0x66, 0x21, 0x63, 0x62,
0xfe, 0xc4, 0xe4, 0x87, 0xc8, 0x26, 0xab, 0xf9, 0x23, 0xf0, 0xc5, 0xd9, 0x54, 0x08, 0x59, 0x8b,
0x4f, 0x93, 0x5e, 0x5b, 0x95, 0xd8, 0xd5, 0x55, 0x4d, 0x80, 0x4a, 0x38, 0x6f, 0x1d, 0xc3, 0x82,
0xed, 0x8e, 0xce, 0x3d, 0x5f, 0xf0, 0xc1, 0x9f, 0xf9, 0xda, 0xdb, 0xe7, 0x56, 0x1b, 0xd3, 0xa3,
0xd4, 0x66, 0x8a, 0xcc, 0x8c, 0x0f, 0xa1, 0xa6, 0x81, 0x49, 0x15, 0x4a, 0x07, 0xdd, 0xc3, 0xed,
0x7e, 0xf3, 0x06, 0x69, 0x40, 0xd5, 0xec, 0xec, 0xf4, 0xbf, 0xec, 0x98, 0x9d, 0xdd, 0x66, 0x8e,
0x54, 0xa0, 0x78, 0xd0, 0x1f, 0x0c, 0x9b, 0x79, 0x63, 0x13, 0x5a, 0x22, 0xc7, 0xf4, 0xe9, 0xd4,
0x6f, 0x17, 0x95, 0x4d, 0x15, 0x91, 0x42, 0xc9, 0xff, 0x08, 0xea, 0xba, 0x78, 0x23, 0x66, 0x44,
0xc2, 0x25, 0x86, 0xa9, 0xf7, 0x9e, 0xc6, 0xab, 0x77, 0x80, 0x3b, 0x44, 0x8c, 0x55, 0xb2, 0x7c,
0x4c, 0x6e, 0xcd, 0x38, 0x59, 0x46, 0xfd, 0x28, 0x36, 0x0d, 0xff, 0x3f, 0x58, 0x8c, 0x9f, 0xc4,
0x08, 0x8e, 0x94, 0xa5, 0xb2, 0xb2, 0xd4, 0xb1, 0xa3, 0x19, 0xf2, 0x3d, 0x68, 0x26, 0x4f, 0x72,
0x84, 0xf0, 0x7c, 0x4d, 0xfa, 0x25, 0x27, 0x7e, 0xb8, 0x43, 0xf6, 0x61, 0x35, 0x4b, 0xc0, 0xc3,
0xf9, 0x71, 0xbd, 0x99, 0x83, 0xa4, 0x85, 0x38, 0xf2, 0x99, 0x38, 0xd1, 0x2b, 0xe1, 0xf0, 0xbf,
0x15, 0x2f, 0x5f, 0xeb, 0xec, 0x2d, 0xfe, 0x4f, 0x3b, 0xdb, 0xbb, 0x00, 0x88, 0x60, 0xa4, 0x09,
0xf5, 0xfe, 0x51, 0xa7, 0x67, 0xed, 0xec, 0xb7, 0x7b, 0xbd, 0xce, 0x41, 0xf3, 0x06, 0x21, 0xb0,
0x88, 0x5e, 0x1d, 0xbb, 0x0a, 0x96, 0x63, 0x30, 0x71, 0xd4, 0x2a, 0x61, 0x79, 0xb2, 0x0a, 0xcd,
0x6e, 0x2f, 0x01, 0x2d, 0x90, 0x16, 0xac, 0x1e, 0x75, 0xb8, 0x23, 0x48, 0x2c, 0xdf, 0x22, 0x53,
0x1a, 0x44, 0x73, 0x8d, 0x10, 0x56, 0xbf, 0xb2, 0x27, 0x13, 0x1a, 0xb6, 0xb9, 0x23, 0xbb, 0x5c,
0x0e, 0xef, 0xc2, 0xb2, 0x32, 0x87, 0x25, 0xa4, 0xe5, 0xa6, 0x42, 0x48, 0xe2, 0x0f, 0x60, 0x45,
0xb3, 0xaa, 0x25, 0x76, 0x21, 0xa2, 0xa1, 0x44, 0x02, 0xa6, 0xaa, 0xf0, 0x52, 0x05, 0x40, 0x4a,
0xf0, 0x7f, 0x94, 0x87, 0xb5, 0x04, 0x22, 0x3a, 0x84, 0xe1, 0xf2, 0x7b, 0xbc, 0x2e, 0x75, 0x04,
0xbe, 0xb0, 0xd2, 0xf9, 0xaf, 0x57, 0xe9, 0xc2, 0x75, 0x95, 0x26, 0x4f, 0x61, 0x49, 0x78, 0xfb,
0x6b, 0x32, 0x1e, 0xe3, 0x11, 0x0f, 0xc4, 0x90, 0x67, 0xd6, 0x7c, 0x2b, 0xde, 0xb1, 0xfc, 0x94,
0x6b, 0xd1, 0x8e, 0x01, 0x37, 0x7f, 0x09, 0x56, 0x32, 0xc8, 0x32, 0xee, 0xbc, 0x7c, 0x18, 0x3f,
0xf1, 0xba, 0x15, 0x2b, 0x39, 0x9e, 0x85, 0x7e, 0x7a, 0xbf, 0x05, 0x0b, 0xc2, 0xda, 0xdb, 0x84,
0x82, 0xbc, 0xf6, 0x54, 0x34, 0xd9, 0x4f, 0x42, 0xa0, 0x38, 0x8d, 0x1c, 0xb0, 0xf1, 0xb7, 0xb1,
0xa1, 0xae, 0x42, 0x26, 0x06, 0xe8, 0x57, 0x8a, 0xb0, 0x9e, 0xc4, 0xa8, 0x2b, 0x09, 0xe5, 0xd8,
0xd8, 0xf0, 0x93, 0x44, 0x01, 0x22, 0x1f, 0x27, 0x96, 0x5b, 0x6c, 0x74, 0x90, 0x54, 0x5f, 0x5a,
0xb2, 0xcb, 0x1f, 0x26, 0x85, 0x6a, 0xce, 0x23, 0x1a, 0xf2, 0x82, 0x06, 0xb6, 0x29, 0x21, 0x63,
0x7f, 0x9c, 0x92, 0xb1, 0x8b, 0x59, 0x89, 0x12, 0x22, 0x77, 0x07, 0x36, 0x22, 0x57, 0xe3, 0x78,
0x99, 0xa5, 0xac, 0xe4, 0x6b, 0x8a, 0xfa, 0x40, 0x2f, 0xfc, 0x31, 0xb4, 0xa2, 0x6c, 0x12, 0xd5,
0x58, 0xc8, 0xca, 0x67, 0x5d, 0x91, 0x9b, 0xb1, 0xfa, 0x7c, 0x1f, 0x36, 0x63, 0xfd, 0x15, 0xaf,
0x52, 0x39, 0x2b, 0xab, 0x0d, 0xad, 0x03, 0x63, 0x95, 0x3a, 0x80, 0x5b, 0xb1, 0xbc, 0x12, 0xf5,
0xaa, 0x64, 0x65, 0xd6, 0xd2, 0x32, 0x8b, 0xd5, 0xcc, 0xf8, 0xdd, 0x05, 0x20, 0x3f, 0x98, 0x53,
0xff, 0x0a, 0x2f, 0x48, 0x07, 0x2f, 0xbb, 0x43, 0x21, 0x2d, 0x95, 0xf9, 0x57, 0x8a, 0x93, 0x90,
0x15, 0xa7, 0xa0, 0xf8, 0xf2, 0x38, 0x05, 0xa5, 0x97, 0xc5, 0x29, 0x78, 0x13, 0x1a, 0xce, 0x99,
0xeb, 0x31, 0x41, 0x80, 0xe9, 0x81, 0x41, 0x6b, 0xe1, 0x6e, 0xe1, 0x5e, 0xdd, 0xac, 0x0b, 0x20,
0xd3, 0x02, 0x03, 0xf2, 0x45, 0x44, 0x44, 0xc7, 0x67, 0x18, 0xc5, 0x43, 0x17, 0x01, 0x3a, 0xe3,
0x33, 0x2a, 0x0c, 0xb3, 0x38, 0x61, 0x65, 0x62, 0x06, 0x0f, 0xc8, 0x5b, 0xb0, 0x18, 0x78, 0x73,
0xa6, 0x56, 0xcb, 0x6e, 0xe0, 0xe7, 0xfd, 0x75, 0x0e, 0x3d, 0x92, 0xde, 0x1f, 0x2b, 0xf3, 0x80,
0x5a, 0x53, 0x27, 0x08, 0x98, 0x72, 0x32, 0xf2, 0xdc, 0xd0, 0xf7, 0x26, 0xe2, 0x08, 0x7f, 0x79,
0x1e, 0xd0, 0x43, 0x8e, 0xd9, 0xe1, 0x08, 0xf2, 0x71, 0x54, 0xa5, 0x99, 0xed, 0xf8, 0x41, 0x0b,
0xb0, 0x4a, 0xb2, 0xa5, 0xa8, 0xbd, 0xda, 0x8e, 0xaf, 0xea, 0xc2, 0x3e, 0x82, 0x44, 0xfc, 0x84,
0x5a, 0x32, 0x7e, 0xc2, 0x2f, 0x67, 0xc7, 0x4f, 0x68, 0xc4, 0x98, 0x59, 0x7a, 0x88, 0xbf, 0x56,
0x18, 0x85, 0x74, 0x58, 0x88, 0xc5, 0xaf, 0x13, 0x16, 0x62, 0x29, 0x2b, 0x2c, 0xc4, 0x87, 0x50,
0xc3, 0xdb, 0xf8, 0xd6, 0x39, 0x3a, 0x33, 0x73, 0x97, 0x84, 0xa6, 0x7e, 0x5d, 0x7f, 0xdf, 0x71,
0x43, 0x13, 0x7c, 0xf9, 0x33, 0x48, 0x47, 0x68, 0x58, 0x7e, 0xa5, 0x08, 0x0d, 0xdf, 0x4c, 0xf8,
0x05, 0x11, 0x35, 0x60, 0x0b, 0x2a, 0x72, 0x9c, 0x18, 0xb3, 0x3d, 0xf5, 0xbd, 0xa9, 0x3c, 0xde,
0x64, 0xbf, 0xc9, 0x22, 0xe4, 0x43, 0x4f, 0x24, 0xce, 0x87, 0x9e, 0xf1, 0x8b, 0x50, 0xd3, 0xa6,
0x1a, 0x79, 0x83, 0xdb, 0xf5, 0x5d, 0x3a, 0x91, 0x66, 0x5f, 0xde, 0x8b, 0x55, 0x01, 0xed, 0x8e,
0xd9, 0xbe, 0x37, 0x76, 0x7c, 0x8a, 0xb1, 0x54, 0x2c, 0x9f, 0x5e, 0x50, 0x3f, 0x90, 0xc7, 0xd2,
0x4d, 0x85, 0x30, 0x39, 0xdc, 0xf8, 0x25, 0x58, 0x89, 0x8d, 0xad, 0x60, 0xdf, 0x6f, 0xc1, 0x02,
0xf6, 0x9b, 0xf4, 0x7d, 0x8a, 0x87, 0x41, 0x10, 0x38, 0x8c, 0x28, 0xc3, 0x4f, 0xd4, 0xad, 0x99,
0xef, 0x9d, 0x60, 0x21, 0x39, 0xb3, 0x26, 0x60, 0x47, 0xbe, 0x77, 0x62, 0xfc, 0xb5, 0x22, 0x14,
0xf6, 0xbd, 0x99, 0xee, 0x00, 0x9d, 0x4b, 0x39, 0x40, 0x0b, 0x73, 0x8b, 0xa5, 0xcc, 0x29, 0x42,
0x63, 0xc5, 0x33, 0x62, 0x69, 0x52, 0xb9, 0x07, 0x8b, 0x8c, 0x4f, 0x84, 0x9e, 0x25, 0x2e, 0x1e,
0xf1, 0xcd, 0x99, 0x2f, 0x3e, 0x7b, 0x1a, 0x0e, 0xbd, 0x3d, 0x0e, 0x27, 0xab, 0x50, 0x50, 0xca,
0x3b, 0xa2, 0xd9, 0x27, 0x59, 0x87, 0x05, 0xbc, 0x30, 0x25, 0xef, 0xcc, 0x8b, 0x2f, 0xf2, 0x3e,
0xac, 0xc4, 0xf3, 0xe5, 0xac, 0x48, 0x68, 0x06, 0x7a, 0xc6, 0xc8, 0x93, 0x6e, 0x02, 0xe3, 0x23,
0xd1, 0xad, 0xf9, 0x82, 0x59, 0x3e, 0xa5, 0x14, 0x51, 0x1a, 0xd3, 0xab, 0xc4, 0x98, 0xde, 0x1d,
0xa8, 0x85, 0x93, 0x0b, 0x6b, 0x66, 0x5f, 0x4d, 0x3c, 0x5b, 0xde, 0xac, 0x84, 0x70, 0x72, 0x71,
0xc4, 0x21, 0xe4, 0x03, 0x80, 0xe9, 0x6c, 0x26, 0xd6, 0x1e, 0x9e, 0x67, 0x46, 0x53, 0xf9, 0xf0,
0xe8, 0x88, 0x4f, 0x39, 0xb3, 0x3a, 0x9d, 0xcd, 0xf8, 0x4f, 0x96, 0xc0, 0x9e, 0xaa, 0x04, 0xf5,
0x58, 0x82, 0xf6, 0xa1, 0x4a, 0x60, 0x4f, 0x65, 0x82, 0x5d, 0x58, 0xcc, 0x0c, 0x90, 0x72, 0x5b,
0xde, 0x43, 0xf1, 0x66, 0x5b, 0x19, 0xab, 0xb9, 0x31, 0xd2, 0x61, 0x9b, 0xdf, 0x03, 0xf2, 0x17,
0x8c, 0x41, 0x32, 0x84, 0xaa, 0x6a, 0x50, 0x2a, 0xf2, 0x49, 0x2d, 0x15, 0xf9, 0x84, 0x31, 0x52,
0x2e, 0xe9, 0xa9, 0x3d, 0x02, 0x34, 0x51, 0x4f, 0xdc, 0xe0, 0x32, 0x4e, 0xa0, 0xaa, 0x5a, 0x8d,
0x67, 0x52, 0x9e, 0x17, 0x5a, 0xc1, 0xb9, 0x2d, 0xae, 0x43, 0xd6, 0xcd, 0x2a, 0x83, 0x0c, 0x18,
0x80, 0xac, 0xc1, 0x42, 0x40, 0xc3, 0xe8, 0xd4, 0xa1, 0x14, 0xd0, 0x90, 0x1f, 0x41, 0x8d, 0xce,
0x9d, 0xc9, 0x38, 0x76, 0x27, 0x1f, 0x10, 0xc4, 0x8f, 0xf5, 0xfe, 0x4b, 0x0e, 0x4a, 0x3c, 0x66,
0xc9, 0xdb, 0xb0, 0xc4, 0xeb, 0xa4, 0x3c, 0xdc, 0x85, 0x1b, 0x12, 0x17, 0x4a, 0x87, 0xc2, 0xb9,
0x9d, 0xad, 0x55, 0x2d, 0x08, 0x54, 0x24, 0xdb, 0x68, 0x81, 0xa0, 0xee, 0x40, 0x55, 0x35, 0x4f,
0x9b, 0xcf, 0x15, 0xd9, 0x3a, 0xf2, 0x3a, 0x14, 0xcf, 0xbd, 0x99, 0x34, 0xc6, 0x42, 0x34, 0x5a,
0x26, 0xc2, 0xa3, 0xba, 0xb0, 0x32, 0xa2, 0xdb, 0x6b, 0x05, 0x51, 0x17, 0x56, 0x88, 0x8c, 0xe4,
0x90, 0xe8, 0xc7, 0x85, 0x8c, 0x7e, 0x3c, 0x86, 0x25, 0xc6, 0x9c, 0x34, 0x5f, 0xa8, 0xeb, 0x77,
0xf2, 0x6f, 0x33, 0xa5, 0x6b, 0x34, 0x99, 0x8f, 0xa9, 0x6e, 0x0e, 0x47, 0x77, 0x65, 0x01, 0x97,
0xca, 0xae, 0xf1, 0xbb, 0x39, 0xce, 0xf4, 0x58, 0xbe, 0xe4, 0x1e, 0x14, 0x5d, 0xe9, 0x37, 0x15,
0xa9, 0x56, 0xea, 0xa6, 0x27, 0xa3, 0x33, 0x91, 0x82, 0x4d, 0x0f, 0xf4, 0x36, 0xd2, 0x73, 0x6f,
0x98, 0x35, 0x77, 0x3e, 0x55, 0xd6, 0xe4, 0x6f, 0xc9, 0x66, 0x25, 0x2c, 0xb1, 0xbc, 0xf5, 0x8a,
0x77, 0x6c, 0x69, 0x7e, 0xcf, 0xc5, 0xd8, 0x36, 0x2e, 0x15, 0xb3, 0xf1, 0x19, 0xd5, 0xfc, 0x9d,
0xff, 0x20, 0x0f, 0x8d, 0x58, 0x8d, 0xd0, 0xf1, 0x9b, 0xed, 0x4a, 0xfc, 0xb4, 0x58, 0x8c, 0x37,
0xfa, 0xd7, 0x0a, 0xdd, 0x59, 0xeb, 0xa7, 0x7c, 0xac, 0x9f, 0x94, 0xe3, 0x63, 0x41, 0x77, 0x7c,
0x7c, 0x00, 0xd5, 0x28, 0xf8, 0x57, 0xbc, 0x4a, 0xac, 0x3c, 0x79, 0xdf, 0x35, 0x22, 0x8a, 0x5c,
0x25, 0x4b, 0xba, 0xab, 0xe4, 0x77, 0x35, 0xcf, 0xba, 0x05, 0xcc, 0xc6, 0xc8, 0xea, 0xd1, 0x9f,
0x8a, 0x5f, 0x9d, 0xf1, 0x05, 0xd4, 0xb4, 0xca, 0xeb, 0xde, 0x69, 0xb9, 0x98, 0x77, 0x9a, 0xba,
0x55, 0x9f, 0x8f, 0x6e, 0xd5, 0x1b, 0xbf, 0x96, 0x87, 0x06, 0x5b, 0x5f, 0x8e, 0x7b, 0x76, 0xe4,
0x4d, 0x9c, 0x11, 0x9e, 0x1e, 0xab, 0x15, 0x26, 0xa4, 0x3f, 0xb9, 0xce, 0xc4, 0x12, 0xe3, 0xc2,
0x9f, 0x1e, 0x54, 0x86, 0xef, 0x1c, 0x2a, 0xa8, 0x8c, 0x01, 0x0d, 0xc6, 0xad, 0xf1, 0x1c, 0x38,
0x0a, 0x14, 0x66, 0xd6, 0x4e, 0x29, 0xdd, 0xb6, 0x03, 0xce, 0xb6, 0xdf, 0x87, 0x15, 0x46, 0x83,
0x71, 0x1e, 0xa6, 0xce, 0x64, 0xe2, 0x44, 0xd7, 0x45, 0x0b, 0x66, 0xf3, 0x94, 0x52, 0xd3, 0x0e,
0xe9, 0x21, 0x43, 0x88, 0xb8, 0x62, 0x95, 0xb1, 0x13, 0xd8, 0x27, 0x91, 0x7b, 0xbe, 0xfa, 0x96,
0xee, 0x15, 0x91, 0x07, 0x8b, 0xf0, 0xbe, 0x12, 0xe1, 0x52, 0x30, 0x7d, 0x62, 0x26, 0x95, 0x93,
0x33, 0xc9, 0xf8, 0x67, 0x79, 0xa8, 0x69, 0xd3, 0xf2, 0x55, 0xb6, 0xfc, 0xdb, 0xa9, 0xd3, 0xfe,
0xaa, 0x7e, 0xb0, 0xff, 0x66, 0xbc, 0xc8, 0x82, 0xba, 0x53, 0xa8, 0x4f, 0xe0, 0x5b, 0x50, 0x65,
0xab, 0xee, 0x43, 0x3c, 0x15, 0x11, 0x11, 0xff, 0x10, 0x70, 0x34, 0x3f, 0x91, 0xc8, 0x87, 0x88,
0x2c, 0x45, 0xc8, 0x87, 0x0c, 0xf9, 0xa2, 0x3b, 0x45, 0x9f, 0x42, 0x5d, 0xe4, 0x8a, 0x63, 0x2a,
0x74, 0x95, 0x55, 0x4d, 0x9c, 0x50, 0xe3, 0x6d, 0xd6, 0x78, 0x71, 0x7c, 0xf0, 0x45, 0xc2, 0x87,
0x32, 0x61, 0xe5, 0x65, 0x09, 0x1f, 0xf2, 0x0f, 0x63, 0x4f, 0x5d, 0xd3, 0x42, 0x9f, 0x56, 0xc9,
0xc7, 0x3e, 0x80, 0x15, 0xc9, 0xae, 0xe6, 0xae, 0xed, 0xba, 0xde, 0xdc, 0x1d, 0x51, 0x79, 0x65,
0x9d, 0x08, 0xd4, 0x71, 0x84, 0x31, 0xc6, 0x2a, 0x14, 0x0d, 0xf7, 0x8d, 0xbd, 0x0f, 0x25, 0xae,
0x2c, 0x70, 0x89, 0x28, 0x9b, 0x71, 0x71, 0x12, 0x72, 0x0f, 0x4a, 0x5c, 0x67, 0xc8, 0x5f, 0xcb,
0x6c, 0x38, 0x81, 0xd1, 0x06, 0xc2, 0x12, 0x1e, 0xd2, 0xd0, 0x77, 0x46, 0x41, 0x74, 0x1b, 0xbe,
0x14, 0x5e, 0xcd, 0x44, 0x59, 0xd1, 0x61, 0x4a, 0x44, 0x89, 0x66, 0x23, 0x4e, 0xc3, 0x36, 0xa6,
0x95, 0x58, 0x1e, 0x42, 0x86, 0x9b, 0xc0, 0xfa, 0x09, 0x0d, 0x9f, 0x53, 0xea, 0xba, 0x4c, 0x42,
0x1b, 0x51, 0x37, 0xf4, 0xed, 0x09, 0x1b, 0x24, 0xde, 0x82, 0x47, 0xa9, 0x5c, 0x23, 0xb3, 0xe4,
0x76, 0x94, 0x70, 0x47, 0xa5, 0xe3, 0xbc, 0x63, 0xed, 0x24, 0x0b, 0xb7, 0xf9, 0x0b, 0xb0, 0x79,
0x7d, 0xa2, 0x0c, 0xdb, 0xc5, 0xbd, 0x38, 0x57, 0x51, 0x47, 0xf3, 0x13, 0xcf, 0x0e, 0x79, 0x6d,
0x74, 0xce, 0xd2, 0x83, 0x9a, 0x86, 0x89, 0xe4, 0x8b, 0x1c, 0x4a, 0x9c, 0xfc, 0x83, 0xed, 0x48,
0xae, 0xe7, 0x4f, 0xf1, 0x28, 0x7c, 0x6c, 0x45, 0xb9, 0xe7, 0xcc, 0xa5, 0x08, 0x8e, 0xde, 0x53,
0xc6, 0x16, 0x2c, 0xa1, 0xba, 0xa1, 0x6d, 0x74, 0x2f, 0x92, 0x50, 0x8d, 0x55, 0x20, 0x3d, 0xce,
0xbb, 0x74, 0x3f, 0xe1, 0x3f, 0x2a, 0x40, 0x4d, 0x03, 0xb3, 0xdd, 0x08, 0x9d, 0xab, 0xad, 0xb1,
0x63, 0x4f, 0xa9, 0xf4, 0x3b, 0x68, 0x98, 0x0d, 0x84, 0xee, 0x0a, 0x20, 0xdb, 0x8b, 0xed, 0x8b,
0x33, 0xcb, 0x9b, 0x87, 0xd6, 0x98, 0x9e, 0xf9, 0x54, 0xd6, 0xb2, 0x6e, 0x5f, 0x9c, 0xf5, 0xe7,
0xe1, 0x2e, 0xc2, 0x64, 0xec, 0x25, 0x8d, 0xaa, 0xa0, 0x62, 0x2f, 0x45, 0x54, 0xc2, 0x29, 0x9d,
0xcf, 0xcc, 0xa2, 0x72, 0x4a, 0xe7, 0x2a, 0x6c, 0x72, 0x03, 0x2d, 0xa5, 0x37, 0xd0, 0x8f, 0x61,
0x9d, 0x6f, 0xa0, 0x82, 0x35, 0x5b, 0x89, 0x95, 0xbc, 0x8a, 0x58, 0xd1, 0x48, 0x4d, 0x16, 0x6f,
0xb2, 0x16, 0x48, 0xb6, 0x14, 0x38, 0x3f, 0xe2, 0x8c, 0x2c, 0x67, 0xb2, 0x96, 0x89, 0xcc, 0x07,
0xce, 0x8f, 0xa8, 0x8c, 0xfd, 0x14, 0xa3, 0x14, 0x37, 0x06, 0xa7, 0x8e, 0x9b, 0xa4, 0xb4, 0x2f,
0xe3, 0x94, 0x55, 0x41, 0x69, 0x5f, 0xea, 0x94, 0x8f, 0x60, 0x63, 0x4a, 0xc7, 0x8e, 0x1d, 0xcf,
0xd6, 0x8a, 0x84, 0xc3, 0x55, 0x8e, 0xd6, 0xd2, 0x0c, 0xb8, 0x35, 0x81, 0xf5, 0xc6, 0x8f, 0xbc,
0xe9, 0x89, 0xc3, 0x65, 0x16, 0xee, 0x17, 0x58, 0x34, 0x17, 0xdd, 0xf9, 0xf4, 0xe7, 0x11, 0xcc,
0x92, 0x04, 0x46, 0x03, 0x6a, 0x83, 0xd0, 0x9b, 0xc9, 0x61, 0x5e, 0x84, 0x3a, 0xff, 0x14, 0xd1,
0x1e, 0x6e, 0xc1, 0x4d, 0x64, 0x09, 0x43, 0x6f, 0xe6, 0x4d, 0xbc, 0xb3, 0xab, 0x98, 0x69, 0xfd,
0x5f, 0xe7, 0x60, 0x25, 0x86, 0x15, 0xec, 0xf5, 0x63, 0xce, 0xcf, 0xd4, 0x4d, 0xf1, 0x5c, 0xec,
0x9a, 0x20, 0x1b, 0x2f, 0x4e, 0xc8, 0x99, 0x99, 0xbc, 0x3d, 0xde, 0x8e, 0x02, 0xab, 0xc9, 0x84,
0x9c, 0xa5, 0xb4, 0xd2, 0x2c, 0x45, 0xa4, 0x97, 0x21, 0xd7, 0x64, 0x16, 0x3f, 0x23, 0x6e, 0x75,
0x8e, 0x45, 0x93, 0x0b, 0xf1, 0x7b, 0x5f, 0xba, 0x19, 0x5e, 0xd6, 0x20, 0xb2, 0xcd, 0x07, 0xc6,
0x9f, 0xe6, 0x01, 0xa2, 0xda, 0x91, 0xbb, 0xba, 0xdc, 0xc2, 0xda, 0xc0, 0x5d, 0x4f, 0x35, 0x39,
0xe5, 0x0d, 0xa8, 0xab, 0x1b, 0x21, 0x91, 0x34, 0x54, 0x93, 0x30, 0x26, 0x12, 0xbd, 0x0b, 0x4b,
0x67, 0x13, 0xef, 0x04, 0xa5, 0x56, 0x21, 0xbb, 0xa0, 0x73, 0x0f, 0x66, 0xb5, 0xc8, 0x51, 0x2a,
0x3c, 0xa2, 0x92, 0x9f, 0x8a, 0x99, 0x17, 0x47, 0x62, 0xd2, 0xd0, 0xe7, 0xb0, 0x88, 0x9d, 0x1c,
0x55, 0xb1, 0x7c, 0xad, 0x68, 0xd5, 0x70, 0xa3, 0x0f, 0x34, 0xf7, 0x24, 0x05, 0xa9, 0x3b, 0xa9,
0xb1, 0xf9, 0xe9, 0x48, 0x51, 0xbf, 0x95, 0x57, 0xfe, 0xf3, 0xd1, 0xb0, 0xbe, 0x58, 0x81, 0xfe,
0x71, 0xbc, 0xfd, 0x5e, 0xe4, 0xbe, 0xf0, 0x05, 0x2c, 0xfa, 0x7c, 0x87, 0x95, 0xdb, 0x6f, 0xf1,
0x05, 0xdb, 0x6f, 0xc3, 0x8f, 0x89, 0x6d, 0xdf, 0x86, 0xa6, 0x3d, 0xbe, 0xa0, 0x7e, 0xe8, 0xe0,
0x69, 0x20, 0x0a, 0xfb, 0xc2, 0x5b, 0x5d, 0x83, 0xa3, 0x54, 0xfd, 0x0e, 0x2c, 0x89, 0x70, 0x2a,
0x8a, 0x52, 0x44, 0x2c, 0x8d, 0xc0, 0x8c, 0xd0, 0xf8, 0xc7, 0xd2, 0x61, 0x3f, 0x3e, 0x55, 0x5f,
0xdc, 0x2b, 0x7a, 0x0b, 0xf3, 0x69, 0x07, 0x0d, 0xb1, 0x2a, 0xc4, 0x21, 0xa3, 0x60, 0xae, 0x1c,
0x28, 0x8e, 0x18, 0xe3, 0xdd, 0x5a, 0x7c, 0x95, 0x6e, 0x35, 0xfe, 0x30, 0x07, 0xe5, 0x7d, 0x6f,
0xb6, 0xef, 0xf0, 0x6b, 0x5f, 0x38, 0x1d, 0xd5, 0x19, 0xf8, 0x02, 0xfb, 0x44, 0xd7, 0xc4, 0x17,
0x5c, 0x07, 0xcf, 0x94, 0x59, 0x1b, 0x71, 0x99, 0xf5, 0xbb, 0x70, 0x0b, 0x5d, 0x0c, 0x7c, 0x6f,
0xe6, 0xf9, 0x8c, 0xef, 0xd8, 0x13, 0x2e, 0xbb, 0x7a, 0x6e, 0x78, 0x2e, 0x37, 0x82, 0x9b, 0xa7,
0x94, 0x1e, 0x69, 0x14, 0x87, 0x8a, 0x00, 0x43, 0x41, 0x4c, 0xc2, 0x0b, 0x8b, 0xdb, 0x40, 0x84,
0x70, 0xcd, 0xb7, 0x87, 0x25, 0x86, 0xe8, 0x20, 0x1c, 0xc5, 0x6b, 0xe3, 0x33, 0xa8, 0x2a, 0x73,
0x1a, 0x79, 0x17, 0xaa, 0xe7, 0xde, 0x4c, 0xd8, 0xdc, 0x72, 0xb1, 0x2b, 0xf3, 0xa2, 0xd5, 0x66,
0xe5, 0x9c, 0xff, 0x08, 0x8c, 0xff, 0x5b, 0x86, 0x72, 0xd7, 0xbd, 0xf0, 0x9c, 0x11, 0xba, 0xf2,
0x4f, 0xe9, 0xd4, 0x93, 0x11, 0xa2, 0xd8, 0x6f, 0xd4, 0xd4, 0xa3, 0xa0, 0xa2, 0x05, 0xa1, 0xa9,
0xab, 0x70, 0xa2, 0x6b, 0xb0, 0xe0, 0xeb, 0x51, 0x41, 0x4b, 0x3e, 0x5e, 0x94, 0x52, 0x9b, 0x7f,
0x49, 0x8b, 0xf4, 0xc5, 0xf2, 0xe2, 0xde, 0xd3, 0xd8, 0x65, 0x3c, 0x9c, 0x43, 0x15, 0x21, 0xd8,
0x61, 0xaf, 0x41, 0x59, 0x58, 0xd6, 0xf9, 0x7d, 0x59, 0x7e, 0x1e, 0x21, 0x40, 0x38, 0x1b, 0x7c,
0xca, 0x5d, 0x44, 0x94, 0x54, 0x5e, 0x30, 0xeb, 0x12, 0xb8, 0x6b, 0x73, 0xff, 0x7c, 0x4e, 0xcf,
0x49, 0xf8, 0x2e, 0x06, 0x1c, 0x84, 0x04, 0x19, 0xf1, 0x77, 0xab, 0x99, 0xf1, 0x77, 0xf1, 0x3e,
0x87, 0xda, 0x32, 0x78, 0x13, 0x81, 0x87, 0x54, 0xd5, 0xe0, 0x32, 0xdc, 0xb5, 0xb0, 0x5a, 0xf1,
0x48, 0x27, 0xd2, 0x6a, 0xf5, 0x26, 0x34, 0x4e, 0xed, 0xc9, 0xe4, 0xc4, 0x1e, 0x3d, 0xe3, 0xb6,
0x93, 0x3a, 0xb7, 0x2f, 0x4b, 0x20, 0x1a, 0x4f, 0xee, 0x40, 0x4d, 0x1b, 0x65, 0x74, 0x5b, 0x2f,
0x9a, 0x10, 0x8d, 0x6f, 0xd2, 0x86, 0xba, 0xf8, 0x0a, 0x36, 0x54, 0xcd, 0x7d, 0x7f, 0x29, 0xee,
0xbe, 0x7f, 0x0b, 0xb7, 0x06, 0x61, 0x3f, 0x69, 0xf2, 0xf8, 0x9d, 0xf6, 0x98, 0x5b, 0x4f, 0xd0,
0x54, 0xc8, 0x3b, 0x8f, 0xe3, 0x97, 0xc5, 0xfd, 0x07, 0x84, 0x71, 0x92, 0xdb, 0xfc, 0x20, 0x60,
0x66, 0x3b, 0x63, 0xbc, 0x9d, 0x26, 0xce, 0x8c, 0xec, 0x69, 0x78, 0x64, 0x3b, 0xe8, 0x0e, 0x2a,
0xd1, 0xb8, 0xd5, 0xaf, 0xf0, 0xfe, 0x17, 0xe8, 0x01, 0x8f, 0xe3, 0xa3, 0x28, 0xa6, 0x2a, 0x54,
0x89, 0x59, 0x13, 0x24, 0x38, 0x0f, 0x3e, 0x44, 0x2f, 0xc2, 0x90, 0x62, 0x30, 0x92, 0x45, 0x75,
0x64, 0x26, 0x66, 0xa9, 0xfc, 0xcf, 0x0f, 0xdf, 0x39, 0x25, 0x93, 0x54, 0xb9, 0x0f, 0xc0, 0x7a,
0x6c, 0x2f, 0x11, 0xa4, 0xe8, 0x03, 0xc0, 0x09, 0xc8, 0x67, 0xda, 0x1e, 0xd2, 0x42, 0xe2, 0xd7,
0x12, 0xf9, 0x5f, 0x77, 0x1f, 0xf8, 0x36, 0x80, 0x13, 0xb0, 0xed, 0x32, 0xa0, 0xee, 0x18, 0x63,
0x8a, 0x54, 0xcc, 0xaa, 0x13, 0x3c, 0xe1, 0x80, 0x94, 0xa1, 0x6c, 0x33, 0x1d, 0x22, 0xf8, 0x1b,
0xdd, 0x82, 0xda, 0x50, 0xd7, 0x7b, 0x82, 0x54, 0xa0, 0xd8, 0x3f, 0xea, 0xf4, 0x9a, 0x37, 0x48,
0x0d, 0xca, 0x83, 0xce, 0x70, 0x78, 0x80, 0xce, 0x06, 0x75, 0xa8, 0xa8, 0xa0, 0x02, 0x79, 0xf6,
0xd5, 0xde, 0xd9, 0xe9, 0x1c, 0x0d, 0x3b, 0xbb, 0xcd, 0xc2, 0xf7, 0x8b, 0x95, 0x7c, 0xb3, 0x60,
0xfc, 0xef, 0x02, 0xd4, 0xb4, 0x8e, 0x7a, 0x31, 0xbf, 0x8e, 0x87, 0xaf, 0xca, 0x27, 0xc3, 0x57,
0xe9, 0x07, 0x45, 0x22, 0xc4, 0x97, 0x3c, 0x28, 0x7a, 0x13, 0x1a, 0x22, 0xba, 0xa8, 0xe6, 0x32,
0x52, 0x32, 0xeb, 0x1c, 0x28, 0xb8, 0x39, 0x86, 0x28, 0x41, 0x22, 0xbc, 0xfc, 0x5d, 0x12, 0xf3,
0x07, 0x41, 0x78, 0xfd, 0x1b, 0xef, 0xee, 0x07, 0xde, 0xe4, 0x82, 0x72, 0x0a, 0x2e, 0x01, 0xd7,
0x04, 0x6c, 0x28, 0xc2, 0xbf, 0x08, 0x96, 0xa9, 0xc5, 0xc8, 0x28, 0x99, 0x75, 0x0e, 0x14, 0x05,
0xbd, 0x2f, 0xe7, 0x18, 0x77, 0xa0, 0xdb, 0x48, 0x4f, 0x98, 0xd8, 0xfc, 0x3a, 0x48, 0x99, 0x66,
0xab, 0x38, 0x77, 0xbe, 0x95, 0x4e, 0xf7, 0x72, 0x13, 0x2d, 0x79, 0x17, 0xc8, 0x74, 0x36, 0xb3,
0x32, 0x8c, 0xa6, 0x45, 0x73, 0x69, 0x3a, 0x9b, 0x0d, 0x35, 0x7b, 0x1f, 0x79, 0x0d, 0x0a, 0xf6,
0x74, 0x86, 0xac, 0x25, 0x32, 0x2e, 0xb6, 0x0f, 0x8f, 0x4c, 0x06, 0xfe, 0x06, 0xac, 0xbd, 0xbf,
0x99, 0x83, 0x42, 0xfb, 0xf0, 0xe8, 0x27, 0x64, 0x92, 0xc5, 0xc8, 0xa7, 0xd1, 0xf6, 0x80, 0xbf,
0xf9, 0x6d, 0x4a, 0xb1, 0xa3, 0xf0, 0xbb, 0x06, 0xea, 0xdb, 0xf8, 0x1b, 0x39, 0x20, 0x6d, 0xc6,
0x91, 0xb0, 0x43, 0x95, 0xa2, 0x1c, 0xed, 0x33, 0x39, 0x7d, 0x9f, 0xc9, 0x60, 0xe7, 0xf9, 0x4c,
0x76, 0xfe, 0x32, 0xc6, 0x17, 0x5b, 0xba, 0xcb, 0xa9, 0xa5, 0x6b, 0xec, 0x41, 0xed, 0x48, 0x8b,
0x5a, 0x7d, 0x97, 0xed, 0x8a, 0x32, 0x5e, 0x35, 0xdf, 0x2f, 0xb9, 0x51, 0xd8, 0x17, 0x61, 0xaa,
0xb5, 0x0a, 0xe7, 0xb5, 0x0a, 0x1b, 0x7f, 0x2f, 0xc7, 0x23, 0x2e, 0xaa, 0xf6, 0x45, 0x81, 0xb2,
0xe5, 0x81, 0x6f, 0x14, 0x9b, 0xa7, 0x26, 0x8f, 0x74, 0x45, 0x58, 0x1d, 0xac, 0xbd, 0xe5, 0x9d,
0x9e, 0x06, 0x54, 0xfa, 0xcd, 0xd5, 0x10, 0xd6, 0x47, 0x90, 0xd4, 0x9e, 0x98, 0x8a, 0xe6, 0xf0,
0xfc, 0x03, 0xe1, 0x2c, 0xc7, 0xb4, 0xa7, 0x43, 0xfb, 0x52, 0x94, 0x1a, 0xb0, 0x11, 0x10, 0xa7,
0x4e, 0x32, 0x36, 0x85, 0xfa, 0x36, 0xfe, 0xb6, 0x08, 0x1f, 0x94, 0x1c, 0x82, 0xfb, 0x50, 0x51,
0xb9, 0xc6, 0xa5, 0x0a, 0x49, 0xa9, 0xf0, 0x4c, 0x76, 0x41, 0x6b, 0x56, 0xac, 0xc6, 0x9c, 0x5b,
0xe0, 0xc9, 0x61, 0x57, 0xab, 0xf5, 0x7b, 0x40, 0x4e, 0x1d, 0x3f, 0x49, 0xcc, 0xb9, 0x47, 0x13,
0x31, 0x1a, 0xb5, 0x71, 0x0c, 0x2b, 0x92, 0xed, 0x69, 0x2a, 0x5d, 0x7c, 0x7c, 0x73, 0x2f, 0xd9,
0xd8, 0xf2, 0xa9, 0x8d, 0xcd, 0xf8, 0x8d, 0x12, 0x94, 0x65, 0x90, 0xf8, 0xac, 0xa8, 0xe5, 0xd5,
0x78, 0xd4, 0xf2, 0x56, 0x2c, 0x92, 0x29, 0x0e, 0xbd, 0x90, 0x71, 0xde, 0x49, 0x8a, 0x29, 0xda,
0x09, 0x58, 0x4c, 0x54, 0x11, 0x27, 0x60, 0xa5, 0xf8, 0x09, 0x58, 0x56, 0x24, 0x77, 0x2e, 0x6e,
0xa7, 0x22, 0xb9, 0xdf, 0x02, 0x2e, 0x3b, 0x69, 0x0e, 0xc3, 0x15, 0x04, 0x88, 0xf8, 0x2a, 0x9a,
0xa8, 0x55, 0x49, 0x8a, 0x5a, 0xaf, 0x2c, 0x06, 0x7d, 0x0c, 0x0b, 0x3c, 0x14, 0x99, 0x88, 0xb5,
0x21, 0x37, 0x4b, 0xd1, 0x57, 0xf2, 0x3f, 0xbf, 0x87, 0x66, 0x0a, 0x5a, 0x3d, 0x5c, 0x6f, 0x2d,
0x16, 0xae, 0x57, 0x3f, 0x99, 0xab, 0xc7, 0x4f, 0xe6, 0xee, 0x41, 0x53, 0x75, 0x1c, 0x9a, 0x94,
0xdd, 0x40, 0x5c, 0xab, 0x5f, 0x94, 0x70, 0xc6, 0xde, 0x7b, 0x41, 0xb4, 0xd9, 0x2f, 0xc6, 0x36,
0x7b, 0xc6, 0x7c, 0xdb, 0x61, 0x48, 0xa7, 0xb3, 0x50, 0x6e, 0xf6, 0x5a, 0xf0, 0x7c, 0x3e, 0xf2,
0xfc, 0x9e, 0x9e, 0x1c, 0x5e, 0x3e, 0x3b, 0xb6, 0x61, 0xf1, 0xd4, 0x76, 0x26, 0x73, 0x9f, 0x5a,
0x3e, 0xb5, 0x03, 0xcf, 0x45, 0xfe, 0x10, 0xc9, 0x1d, 0xa2, 0x89, 0x7b, 0x9c, 0xc6, 0x44, 0x12,
0xb3, 0x71, 0xaa, 0x7f, 0xe2, 0xad, 0x58, 0xbd, 0x27, 0xd8, 0x1e, 0x2c, 0x22, 0x6e, 0x70, 0xff,
0xbf, 0x6e, 0xcf, 0xda, 0x3b, 0xe8, 0x3e, 0xde, 0x1f, 0x36, 0x73, 0xec, 0x73, 0x70, 0xbc, 0xb3,
0xd3, 0xe9, 0xec, 0xe2, 0x9e, 0x0c, 0xb0, 0xb0, 0xd7, 0xee, 0x1e, 0x88, 0x1d, 0xb9, 0xd8, 0x2c,
0x19, 0x7f, 0x94, 0x87, 0x9a, 0xd6, 0x1a, 0x8c, 0xa5, 0xc3, 0x7f, 0x32, 0xfe, 0x5b, 0x16, 0xb1,
0x74, 0x38, 0xa4, 0x3b, 0x26, 0x8f, 0xd4, 0x18, 0xf1, 0x10, 0x40, 0xb7, 0xd3, 0x1d, 0xb2, 0x25,
0x77, 0x34, 0x6d, 0x90, 0x54, 0x14, 0xfd, 0xfc, 0xb5, 0x51, 0xf4, 0xc9, 0xdb, 0xb0, 0x24, 0x4b,
0x96, 0x63, 0x22, 0x0e, 0x6f, 0x04, 0x58, 0x0c, 0xc9, 0xdb, 0x22, 0x1c, 0x91, 0xd8, 0x96, 0x19,
0x5d, 0x51, 0xfa, 0xc9, 0xab, 0x9d, 0x19, 0x87, 0xae, 0x2c, 0x3a, 0x4e, 0x78, 0x80, 0x28, 0x01,
0x47, 0x74, 0xa7, 0x44, 0xc7, 0xf6, 0x88, 0x85, 0xc4, 0x1e, 0xf1, 0x09, 0x40, 0xd4, 0x9e, 0x78,
0xef, 0xde, 0x88, 0xf7, 0x6e, 0x4e, 0xeb, 0xdd, 0xbc, 0xf1, 0x8f, 0x04, 0x67, 0x13, 0x43, 0xa5,
0x4c, 0xb9, 0xef, 0x83, 0x34, 0x2e, 0x5b, 0x78, 0xaf, 0x66, 0x36, 0xa1, 0xa1, 0x0c, 0x1a, 0xb0,
0x2c, 0x30, 0x5d, 0x85, 0x48, 0x71, 0xe2, 0x7c, 0x9a, 0x13, 0xbf, 0x01, 0x75, 0x8c, 0x6f, 0x29,
0x0a, 0x92, 0x01, 0xa6, 0xa7, 0xf6, 0xa5, 0x2c, 0x3b, 0xc6, 0x82, 0x8b, 0x09, 0x16, 0xfc, 0x77,
0x72, 0x3c, 0x18, 0x5a, 0x54, 0xd1, 0x88, 0x07, 0xab, 0x3c, 0xe3, 0x3c, 0x58, 0x90, 0x9a, 0x0a,
0x7f, 0x0d, 0x5f, 0xcd, 0x67, 0xf3, 0xd5, 0x6c, 0x8e, 0x5d, 0xc8, 0xe4, 0xd8, 0xc6, 0x25, 0xb4,
0x76, 0x29, 0xeb, 0x8a, 0xf6, 0x64, 0x92, 0xec, 0xcb, 0x07, 0xb0, 0xca, 0x86, 0x10, 0xdd, 0x5f,
0x38, 0x46, 0xdf, 0xd1, 0x08, 0xc7, 0xc9, 0x44, 0xb8, 0xb1, 0xdd, 0x87, 0x65, 0x91, 0x02, 0x17,
0xad, 0x1e, 0x79, 0x6e, 0x89, 0x23, 0xd0, 0x6d, 0x97, 0xd1, 0x1a, 0xb7, 0xe0, 0x66, 0x46, 0xc9,
0xc2, 0xe6, 0xf7, 0x9b, 0x39, 0x58, 0x6b, 0xf3, 0x08, 0x4b, 0xdf, 0x58, 0xcc, 0x80, 0xcf, 0xe1,
0xa6, 0xba, 0x82, 0xa3, 0x5d, 0x1d, 0xd6, 0x2b, 0x29, 0x6f, 0xef, 0x68, 0x17, 0xcf, 0xb0, 0xae,
0x2d, 0x58, 0x4f, 0xd6, 0x46, 0x54, 0x74, 0x0f, 0x96, 0x77, 0xe9, 0xc9, 0xfc, 0xec, 0x80, 0x5e,
0x44, 0x75, 0x24, 0x50, 0x0c, 0xce, 0xbd, 0xe7, 0xa2, 0xa3, 0xf0, 0x37, 0xfa, 0xe8, 0x33, 0x1a,
0x2b, 0x98, 0xd1, 0x91, 0x3c, 0x33, 0x42, 0xc8, 0x60, 0x46, 0x47, 0xc6, 0x23, 0x20, 0x7a, 0x3e,
0x62, 0x8e, 0x30, 0x1d, 0x78, 0x7e, 0x62, 0x05, 0x57, 0x41, 0x48, 0xa7, 0xf2, 0xfa, 0x3c, 0x04,
0xf3, 0x93, 0x01, 0x87, 0x18, 0xef, 0x40, 0xfd, 0xc8, 0xbe, 0x32, 0xe9, 0x0f, 0xc5, 0x0d, 0xf4,
0x0d, 0x28, 0xcf, 0xec, 0x2b, 0xb6, 0x11, 0xa8, 0xe3, 0x63, 0x44, 0x1b, 0xbf, 0x57, 0x84, 0x05,
0x4e, 0x49, 0xee, 0xf2, 0x07, 0x76, 0x1c, 0x17, 0x19, 0xb1, 0xdc, 0x12, 0x35, 0x50, 0x6a, 0xd7,
0xcc, 0xa7, 0x77, 0x4d, 0x61, 0xeb, 0x96, 0xe1, 0x3b, 0xe5, 0x41, 0x9f, 0x3b, 0x9f, 0xca, 0x98,
0x9d, 0xf1, 0x78, 0x42, 0xc5, 0xe8, 0xc9, 0x26, 0x1e, 0x4b, 0x25, 0xee, 0x1f, 0x12, 0x69, 0xda,
0xbc, 0x76, 0x52, 0x18, 0x10, 0x1b, 0xa6, 0x0e, 0xca, 0x54, 0xe7, 0xcb, 0x32, 0x3c, 0x43, 0x5c,
0x9d, 0x4f, 0xa9, 0xed, 0x95, 0x97, 0xab, 0xed, 0xdc, 0x08, 0xfe, 0x02, 0xb5, 0x1d, 0x5e, 0x41,
0x6d, 0x7f, 0x05, 0x57, 0x8b, 0x9b, 0x50, 0x41, 0x09, 0x4f, 0xdb, 0x3f, 0x99, 0x64, 0xc7, 0xf6,
0xcf, 0x4f, 0x35, 0xc5, 0x96, 0x3b, 0x86, 0x69, 0x1b, 0x98, 0x49, 0x7f, 0xf8, 0xd3, 0x31, 0x8c,
0x3e, 0x85, 0xb2, 0x80, 0xb2, 0x09, 0xed, 0xda, 0x53, 0x19, 0xa4, 0x1a, 0x7f, 0xb3, 0x6e, 0xc3,
0xb0, 0xad, 0x3f, 0x9c, 0x3b, 0x3e, 0x1d, 0xcb, 0xe0, 0x91, 0x0e, 0x72, 0x0f, 0x06, 0x61, 0x0d,
0x64, 0x4a, 0xb6, 0x2b, 0xdf, 0xd6, 0xa8, 0x98, 0x65, 0x27, 0x78, 0xc2, 0x3e, 0x0d, 0x02, 0x4d,
0x7c, 0x12, 0x60, 0xe6, 0xf9, 0x52, 0x3c, 0x31, 0x7e, 0x3f, 0x07, 0x4d, 0xb1, 0xba, 0x14, 0x4e,
0x57, 0x60, 0x4b, 0xd7, 0xf9, 0x31, 0xbd, 0x38, 0x14, 0xa4, 0x01, 0x0d, 0x34, 0xed, 0x29, 0x59,
0x85, 0x9b, 0x26, 0x6b, 0x0c, 0xb8, 0x27, 0xe4, 0x95, 0xd7, 0xa1, 0x26, 0x6f, 0x10, 0x4d, 0x9d,
0x89, 0x7c, 0x9d, 0x8d, 0x5f, 0x21, 0x3a, 0x74, 0x26, 0x52, 0xd4, 0xf1, 0x6d, 0x11, 0x32, 0x24,
0x87, 0xa2, 0x8e, 0x69, 0x87, 0xd4, 0xf8, 0x27, 0x39, 0x58, 0xd6, 0x9a, 0x22, 0xd6, 0xed, 0x77,
0xa0, 0xae, 0xde, 0x3c, 0xa1, 0x4a, 0xc6, 0xde, 0x88, 0xf3, 0xa8, 0x28, 0x59, 0x6d, 0xa4, 0x20,
0x01, 0xab, 0xcc, 0xd8, 0xbe, 0xe2, 0xd7, 0x5c, 0xe6, 0x53, 0xa9, 0x97, 0x8f, 0xed, 0xab, 0x3d,
0x4a, 0x07, 0xf3, 0x29, 0xb9, 0x0b, 0xf5, 0xe7, 0x94, 0x3e, 0x53, 0x04, 0x9c, 0xb1, 0x03, 0x83,
0x09, 0x0a, 0x03, 0x1a, 0x53, 0xcf, 0x0d, 0xcf, 0x15, 0x89, 0xd0, 0x2f, 0x10, 0xc8, 0x69, 0x8c,
0x7f, 0x9b, 0x87, 0x15, 0x6e, 0x40, 0x16, 0xa7, 0x10, 0x82, 0x75, 0xb5, 0x60, 0x81, 0x1f, 0x08,
0x70, 0xe6, 0xb5, 0x7f, 0xc3, 0x14, 0xdf, 0xe4, 0xe3, 0x57, 0x34, 0x7a, 0xcb, 0x68, 0x23, 0xd7,
0x74, 0x7f, 0x21, 0xdd, 0xfd, 0xd7, 0x77, 0x6f, 0x96, 0x4f, 0x42, 0x29, 0xcb, 0x27, 0xe1, 0x55,
0x3c, 0x01, 0x52, 0xf1, 0x2e, 0xca, 0xe9, 0xb8, 0xd3, 0x8f, 0x60, 0x23, 0x46, 0x83, 0xdc, 0xda,
0x39, 0x75, 0xd4, 0x83, 0x09, 0xab, 0x1a, 0xf5, 0x40, 0xe2, 0xb6, 0xcb, 0x50, 0x0a, 0x46, 0xde,
0x0c, 0x7d, 0xeb, 0xe3, 0xbd, 0x2a, 0xb6, 0x89, 0xdf, 0xc9, 0x41, 0x6b, 0x2f, 0x0a, 0xe0, 0xed,
0x04, 0xa1, 0xe7, 0xab, 0xb7, 0x28, 0x6e, 0x03, 0xf0, 0x97, 0xe2, 0xd0, 0x0c, 0x22, 0x22, 0xaf,
0x21, 0x04, 0x8d, 0x20, 0x37, 0xa1, 0x42, 0xdd, 0x31, 0x47, 0xf2, 0xd9, 0x50, 0xa6, 0xee, 0x58,
0x9a, 0x50, 0x52, 0x9b, 0x7c, 0x23, 0x2e, 0xbe, 0x88, 0x18, 0x42, 0xac, 0x77, 0xe8, 0x05, 0x0a,
0x1b, 0x45, 0x15, 0x43, 0xe8, 0xd0, 0xbe, 0xc4, 0x2b, 0x12, 0x81, 0xf1, 0x4f, 0xf3, 0xb0, 0x14,
0xd5, 0x8f, 0x47, 0x51, 0xbb, 0x9b, 0x8a, 0x07, 0x27, 0xdc, 0xa9, 0x14, 0x0f, 0xbf, 0x2b, 0xa6,
0x84, 0xc3, 0xb4, 0x35, 0xcd, 0xb4, 0x5e, 0xe1, 0x0b, 0xb4, 0xeb, 0x12, 0x03, 0x6a, 0x92, 0xc2,
0x9b, 0x87, 0x5a, 0xbc, 0xec, 0x2a, 0x27, 0xe9, 0xcf, 0x43, 0xa6, 0x5e, 0xdb, 0x53, 0x26, 0xad,
0x08, 0x05, 0xb7, 0x64, 0x4f, 0xc3, 0x2e, 0x3e, 0x49, 0xc8, 0xc0, 0x2c, 0x19, 0x1f, 0x4c, 0x46,
0xc5, 0xe8, 0x9b, 0x5c, 0xdb, 0xe2, 0xa3, 0x87, 0x9a, 0x96, 0xae, 0x8a, 0xf0, 0x87, 0x90, 0x94,
0x2a, 0xf2, 0x3a, 0xd4, 0x78, 0xe6, 0x51, 0x88, 0x13, 0x0c, 0x5e, 0x19, 0x76, 0x5d, 0xc4, 0x0b,
0x33, 0xa7, 0x37, 0x8f, 0x59, 0x6e, 0x80, 0x17, 0x25, 0x5f, 0x8f, 0x53, 0x2d, 0xb6, 0xd4, 0x19,
0x66, 0x4d, 0xc1, 0x7a, 0x01, 0x93, 0x56, 0x6e, 0x66, 0x8c, 0xae, 0x60, 0x06, 0x3b, 0xa0, 0x45,
0x7b, 0x97, 0x83, 0xc0, 0x39, 0xc2, 0xba, 0xe4, 0xbe, 0xf1, 0xae, 0x37, 0x9b, 0xa7, 0x71, 0x40,
0xa4, 0x85, 0xf3, 0x81, 0x8e, 0xc5, 0xe2, 0x41, 0x99, 0x8e, 0x8f, 0x36, 0x57, 0x80, 0x8f, 0x60,
0xb3, 0x73, 0xc9, 0x18, 0x8b, 0xba, 0x2c, 0x30, 0x7a, 0x36, 0x97, 0xc7, 0xab, 0x89, 0x53, 0x96,
0xdc, 0x2b, 0x9d, 0xb2, 0x8c, 0x79, 0x04, 0x0c, 0x95, 0xd7, 0x8f, 0x93, 0x09, 0xb7, 0x2f, 0xd9,
0xae, 0x75, 0x82, 0x59, 0xc8, 0x80, 0x3b, 0x0c, 0xc4, 0x33, 0x35, 0x02, 0x58, 0x3a, 0x9c, 0x4f,
0x42, 0x67, 0x47, 0x81, 0xc8, 0xc7, 0x22, 0x0d, 0x96, 0x23, 0x7b, 0x2d, 0xb3, 0x20, 0x50, 0x05,
0x61, 0x67, 0x4d, 0x59, 0x46, 0x56, 0xba, 0xbc, 0xa5, 0x69, 0xbc, 0x04, 0xe3, 0x26, 0x6c, 0x44,
0x5f, 0xbc, 0xdb, 0xe4, 0x8e, 0xf4, 0x77, 0x73, 0xfc, 0xda, 0x16, 0xc7, 0x0d, 0x5c, 0x7b, 0x16,
0x9c, 0x7b, 0x21, 0xe9, 0xc0, 0x4a, 0xe0, 0xb8, 0x67, 0x13, 0xaa, 0x67, 0x1f, 0x88, 0x4e, 0x58,
0x8b, 0xd7, 0x8d, 0x27, 0x0d, 0xcc, 0x65, 0x9e, 0x22, 0xca, 0x2d, 0x20, 0xdb, 0xd7, 0x55, 0x32,
0x9a, 0x16, 0x89, 0xde, 0x48, 0x57, 0xbe, 0x0b, 0x8b, 0xf1, 0x82, 0xc8, 0xa7, 0x22, 0x70, 0x4c,
0x54, 0xab, 0x42, 0x22, 0x6c, 0x46, 0x34, 0x21, 0x6a, 0x51, 0xdf, 0x07, 0xc6, 0x5f, 0xcf, 0x41,
0xcb, 0xa4, 0x6c, 0xe6, 0x6a, 0xb5, 0x94, 0x73, 0xe6, 0x3b, 0xa9, 0x5c, 0xaf, 0x6f, 0xab, 0x8c,
0x47, 0x23, 0x6b, 0xf4, 0xde, 0xb5, 0x83, 0xb1, 0x7f, 0x23, 0xd5, 0xa2, 0xed, 0x0a, 0x2c, 0x70,
0x12, 0x63, 0x03, 0xd6, 0x44, 0x7d, 0x64, 0x5d, 0x22, 0x7f, 0x80, 0x58, 0x89, 0x31, 0x7f, 0x80,
0x4d, 0x68, 0xf1, 0xf8, 0x0e, 0x7a, 0x23, 0x44, 0xc2, 0x5d, 0x20, 0x87, 0xf6, 0xc8, 0xf6, 0x3d,
0xcf, 0x3d, 0xa2, 0xbe, 0xb8, 0x06, 0x80, 0x82, 0x28, 0x1e, 0x95, 0x4b, 0x89, 0x99, 0x7f, 0xc9,
0x87, 0x04, 0x3c, 0x57, 0x3a, 0x18, 0xf2, 0x2f, 0xc3, 0x87, 0x95, 0x6d, 0xfb, 0x19, 0x95, 0x39,
0xc9, 0x2e, 0xfa, 0x02, 0x6a, 0x33, 0x95, 0xa9, 0xec, 0x77, 0x19, 0x93, 0x2b, 0x5d, 0xac, 0xa9,
0x53, 0x33, 0x2e, 0x85, 0x06, 0x5b, 0x8c, 0x72, 0x33, 0x96, 0x7b, 0x3e, 0x03, 0x3d, 0xa1, 0x57,
0xdd, 0xb1, 0xf1, 0x10, 0x56, 0xe3, 0x65, 0x0a, 0xd6, 0xb2, 0x09, 0x95, 0xa9, 0x80, 0x89, 0xda,
0xab, 0x6f, 0xa6, 0xb3, 0x30, 0xbd, 0x53, 0xa6, 0xe9, 0xee, 0xaa, 0x50, 0x0d, 0x5f, 0xc0, 0x46,
0x0a, 0x23, 0x32, 0xbc, 0x0b, 0x75, 0xad, 0x22, 0xbc, 0x19, 0x45, 0x13, 0x54, 0x4d, 0x02, 0xe3,
0x73, 0xd8, 0xe0, 0x6a, 0x5b, 0x94, 0x5c, 0x76, 0x41, 0xa2, 0x15, 0xb9, 0x64, 0x2b, 0x3e, 0x96,
0xba, 0xa6, 0x9e, 0x34, 0x8a, 0x89, 0x39, 0x46, 0x9c, 0xf4, 0x11, 0x93, 0x9f, 0xc6, 0x31, 0xac,
0xa7, 0xbb, 0x8f, 0xd5, 0xff, 0x2f, 0xd4, 0xe5, 0xb2, 0x7b, 0x22, 0xb4, 0xea, 0x9e, 0xff, 0x9a,
0xe3, 0xfd, 0x13, 0x43, 0x89, 0x6a, 0x8e, 0x81, 0x4c, 0x69, 0x78, 0xee, 0x8d, 0xad, 0x74, 0xc9,
0x8f, 0x94, 0x8b, 0x5a, 0x66, 0xda, 0xad, 0x43, 0x4c, 0xa8, 0x61, 0xc4, 0x0d, 0x8e, 0x69, 0x12,
0xbe, 0x39, 0x82, 0xf5, 0x6c, 0xe2, 0x0c, 0xc7, 0xae, 0x8f, 0xe2, 0xf2, 0xfc, 0xed, 0x6b, 0x9b,
0xcf, 0xaa, 0xa5, 0x8b, 0xf7, 0xbf, 0x57, 0x81, 0xb2, 0x30, 0xd5, 0x90, 0x2d, 0x28, 0x8e, 0xa4,
0x93, 0x70, 0x14, 0x17, 0x55, 0x60, 0xe5, 0xff, 0x1d, 0x74, 0x15, 0x66, 0x74, 0xe4, 0x0b, 0x58,
0x8c, 0xfb, 0xc9, 0x24, 0xe2, 0x17, 0xc5, 0x1d, 0x5c, 0x1a, 0xa3, 0x84, 0x13, 0x41, 0x35, 0x92,
0xc1, 0xb8, 0x68, 0x5a, 0x39, 0xd7, 0x84, 0x34, 0xcf, 0x65, 0x6a, 0x5d, 0x70, 0x6e, 0x5b, 0x0f,
0x1f, 0x7d, 0x22, 0x0e, 0x15, 0x6a, 0x08, 0x1c, 0x9c, 0xdb, 0x0f, 0x1f, 0x7d, 0x92, 0x54, 0xd8,
0x44, 0xf8, 0x22, 0x4d, 0x61, 0x5b, 0x85, 0x12, 0x7f, 0x6d, 0x81, 0x7b, 0x7b, 0xf2, 0x0f, 0x69,
0xce, 0x98, 0xfb, 0xd4, 0x12, 0x97, 0x85, 0xf8, 0x2e, 0xca, 0xdf, 0xd8, 0x23, 0x02, 0x37, 0x40,
0x14, 0x37, 0x27, 0xae, 0xc3, 0xc2, 0x79, 0xf4, 0x7c, 0x46, 0xc3, 0x14, 0x5f, 0xc6, 0x9f, 0x96,
0xa0, 0xa6, 0x75, 0x0a, 0xa9, 0x43, 0xc5, 0xec, 0x0c, 0x3a, 0xe6, 0x97, 0x9d, 0xdd, 0xe6, 0x0d,
0x72, 0x0f, 0xde, 0xea, 0xf6, 0x76, 0xfa, 0xa6, 0xd9, 0xd9, 0x19, 0x5a, 0x7d, 0xd3, 0x92, 0xe1,
0x7a, 0x8f, 0xda, 0x4f, 0x0f, 0x3b, 0xbd, 0xa1, 0xb5, 0xdb, 0x19, 0xb6, 0xbb, 0x07, 0x83, 0x66,
0x8e, 0xbc, 0x06, 0xad, 0x88, 0x52, 0xa2, 0xdb, 0x87, 0xfd, 0xe3, 0xde, 0xb0, 0x99, 0x27, 0x77,
0xe0, 0xd6, 0x5e, 0xb7, 0xd7, 0x3e, 0xb0, 0x22, 0x9a, 0x9d, 0x83, 0xe1, 0x97, 0x56, 0xe7, 0xe7,
0x8e, 0xba, 0xe6, 0xd3, 0x66, 0x21, 0x8b, 0x60, 0x7f, 0x78, 0xb0, 0x23, 0x73, 0x28, 0x92, 0x9b,
0xb0, 0xc6, 0x09, 0x78, 0x12, 0x6b, 0xd8, 0xef, 0x5b, 0x83, 0x7e, 0xbf, 0xd7, 0x2c, 0x91, 0x65,
0x68, 0x74, 0x7b, 0x5f, 0xb6, 0x0f, 0xba, 0xbb, 0x96, 0xd9, 0x69, 0x1f, 0x1c, 0x36, 0x17, 0xc8,
0x0a, 0x2c, 0x25, 0xe9, 0xca, 0x2c, 0x0b, 0x49, 0xd7, 0xef, 0x75, 0xfb, 0x3d, 0xeb, 0xcb, 0x8e,
0x39, 0xe8, 0xf6, 0x7b, 0xcd, 0x0a, 0x59, 0x07, 0x12, 0x47, 0xed, 0x1f, 0xb6, 0x77, 0x9a, 0x55,
0xb2, 0x06, 0xcb, 0x71, 0xf8, 0x93, 0xce, 0xd3, 0x26, 0x90, 0x16, 0xac, 0xf2, 0x8a, 0x59, 0xdb,
0x9d, 0x83, 0xfe, 0x57, 0xd6, 0x61, 0xb7, 0xd7, 0x3d, 0x3c, 0x3e, 0x6c, 0xd6, 0x30, 0x68, 0x7a,
0xa7, 0x63, 0x75, 0x7b, 0x83, 0xe3, 0xbd, 0xbd, 0xee, 0x4e, 0xb7, 0xd3, 0x1b, 0x36, 0xeb, 0xbc,
0xe4, 0xac, 0x86, 0x37, 0x58, 0x02, 0x71, 0x9f, 0xd6, 0xda, 0xed, 0x0e, 0xda, 0xdb, 0x07, 0x9d,
0xdd, 0xe6, 0x22, 0xb9, 0x0d, 0x37, 0x87, 0x9d, 0xc3, 0xa3, 0xbe, 0xd9, 0x36, 0x9f, 0xca, 0xfb,
0xb6, 0xd6, 0x5e, 0xbb, 0x7b, 0x70, 0x6c, 0x76, 0x9a, 0x4b, 0xe4, 0x0d, 0xb8, 0x6d, 0x76, 0x7e,
0x70, 0xdc, 0x35, 0x3b, 0xbb, 0x56, 0xaf, 0xbf, 0xdb, 0xb1, 0xf6, 0x3a, 0xed, 0xe1, 0xb1, 0xd9,
0xb1, 0x0e, 0xbb, 0x83, 0x41, 0xb7, 0xf7, 0xb8, 0xd9, 0x24, 0x6f, 0xc1, 0x5d, 0x45, 0xa2, 0x32,
0x48, 0x50, 0x2d, 0xb3, 0xf6, 0xc9, 0x21, 0xed, 0x75, 0x7e, 0x6e, 0x68, 0x1d, 0x75, 0x3a, 0x66,
0x93, 0x90, 0x4d, 0x58, 0x8f, 0x8a, 0xe7, 0x05, 0x88, 0xb2, 0x57, 0x18, 0xee, 0xa8, 0x63, 0x1e,
0xb6, 0x7b, 0x6c, 0x80, 0x63, 0xb8, 0x55, 0x56, 0xed, 0x08, 0x97, 0xac, 0xf6, 0x1a, 0x21, 0xb0,
0xa8, 0x8d, 0xca, 0x5e, 0xdb, 0x6c, 0xae, 0x93, 0x25, 0xa8, 0x1d, 0x1e, 0x1d, 0x59, 0xc3, 0xee,
0x61, 0xa7, 0x7f, 0x3c, 0x6c, 0x6e, 0xa4, 0x47, 0xe9, 0xa8, 0xfd, 0xf4, 0xa0, 0xdf, 0xde, 0x6d,
0xb6, 0xc8, 0x1a, 0x34, 0xbb, 0xbd, 0x61, 0xc7, 0x64, 0xd3, 0x40, 0xe6, 0xfa, 0xdf, 0xca, 0x64,
0x15, 0x96, 0x64, 0x23, 0x24, 0xf4, 0x8f, 0xcb, 0x64, 0x03, 0xc8, 0x71, 0xcf, 0xec, 0xb4, 0x77,
0x59, 0x9f, 0x2a, 0xc4, 0x7f, 0x2f, 0x8b, 0xe3, 0xe5, 0xdf, 0x2f, 0x28, 0x39, 0x50, 0xac, 0xe5,
0xd4, 0x53, 0x58, 0x75, 0xed, 0x09, 0xab, 0x97, 0x3d, 0xbc, 0xaa, 0x29, 0xf7, 0x85, 0x94, 0x72,
0x9f, 0xb2, 0x1e, 0x35, 0x74, 0xcd, 0xe3, 0x4d, 0x68, 0x4c, 0xf9, 0xb3, 0x58, 0xe2, 0x5d, 0x15,
0x10, 0xce, 0x9a, 0x1c, 0xc8, 0x1f, 0x55, 0x49, 0xbd, 0x3c, 0x5a, 0x4a, 0xbf, 0x3c, 0x9a, 0xa5,
0x61, 0x2e, 0x64, 0x69, 0x98, 0xf7, 0x61, 0x99, 0x73, 0x2d, 0xc7, 0x75, 0xa6, 0xd2, 0x6e, 0x23,
0xde, 0xf1, 0x44, 0xee, 0xc5, 0xe1, 0x52, 0xa1, 0x95, 0x4a, 0xaf, 0xe0, 0x2e, 0x65, 0xa1, 0xef,
0xc6, 0x74, 0x5d, 0xce, 0x54, 0x94, 0xae, 0xab, 0x4a, 0xb0, 0x2f, 0xa3, 0x12, 0x6a, 0x5a, 0x09,
0x1c, 0x8e, 0x25, 0xdc, 0x87, 0x65, 0x7a, 0x19, 0xfa, 0xb6, 0xe5, 0xcd, 0xec, 0x1f, 0xce, 0xd1,
0x45, 0xc6, 0x46, 0x2b, 0x52, 0xdd, 0x5c, 0x42, 0x44, 0x1f, 0xe1, 0xbb, 0x76, 0x68, 0x1b, 0xbf,
0x08, 0xa0, 0x36, 0x5c, 0x7c, 0x0f, 0xd5, 0xf5, 0xe4, 0x3d, 0xe1, 0xba, 0xc9, 0x3f, 0x70, 0x1c,
0x43, 0xcf, 0xb7, 0xcf, 0x68, 0x57, 0x9e, 0x0a, 0x47, 0x00, 0x72, 0x0b, 0x0a, 0xde, 0x4c, 0xba,
0x32, 0x56, 0xe5, 0x43, 0x01, 0x33, 0x93, 0x41, 0x8d, 0x4f, 0x20, 0xdf, 0x9f, 0x5d, 0x2b, 0x45,
0xe1, 0xa3, 0x6d, 0xfc, 0xa5, 0x86, 0x3c, 0x46, 0x28, 0x96, 0x9f, 0xf7, 0xff, 0x32, 0xd4, 0xb4,
0x37, 0xde, 0xc8, 0x06, 0xac, 0x7c, 0xd5, 0x1d, 0xf6, 0x3a, 0x83, 0x81, 0x75, 0x74, 0xbc, 0xfd,
0xa4, 0xf3, 0xd4, 0xda, 0x6f, 0x0f, 0xf6, 0x9b, 0x37, 0x18, 0x9b, 0xe9, 0x75, 0x06, 0xc3, 0xce,
0x6e, 0x0c, 0x9e, 0x23, 0xaf, 0xc3, 0xe6, 0x71, 0xef, 0x78, 0xd0, 0xd9, 0xb5, 0xb2, 0xd2, 0xe5,
0xd9, 0xba, 0x12, 0xf8, 0x8c, 0xe4, 0x85, 0xfb, 0xbf, 0x04, 0x8b, 0xf1, 0x60, 0x39, 0x04, 0x60,
0xe1, 0xa0, 0xf3, 0xb8, 0xbd, 0xf3, 0x94, 0x3f, 0x04, 0x31, 0x18, 0xb6, 0x87, 0xdd, 0x1d, 0x4b,
0x3c, 0xfc, 0xc0, 0x78, 0x58, 0x8e, 0xd4, 0xa0, 0xdc, 0xee, 0xed, 0xec, 0xf7, 0xcd, 0x41, 0x33,
0x4f, 0x5e, 0x83, 0x0d, 0xb9, 0x84, 0x76, 0xfa, 0x87, 0x87, 0xdd, 0x21, 0xb2, 0xef, 0xe1, 0xd3,
0x23, 0xb6, 0x62, 0xee, 0xdb, 0x50, 0x8d, 0xde, 0xac, 0x40, 0x96, 0xd8, 0x1d, 0x76, 0xdb, 0xc3,
0x68, 0x3f, 0x68, 0xde, 0x60, 0x1c, 0x37, 0x02, 0xe3, 0xc3, 0x13, 0xcd, 0x1c, 0x8f, 0x27, 0x20,
0x81, 0xbc, 0xf4, 0x66, 0x9e, 0xb1, 0x81, 0x08, 0xba, 0xdd, 0x1f, 0xb2, 0x26, 0xfc, 0x32, 0x2c,
0xc6, 0x9f, 0x86, 0x20, 0x4d, 0xa8, 0xb3, 0xf2, 0xb5, 0x22, 0x00, 0x16, 0x78, 0x8d, 0x9b, 0x39,
0xce, 0xf3, 0x77, 0xfa, 0x87, 0xdd, 0xde, 0x63, 0xdc, 0x28, 0x9a, 0x79, 0x06, 0xea, 0x1f, 0x0f,
0x1f, 0xf7, 0x15, 0xa8, 0xc0, 0x52, 0xf0, 0xe6, 0x34, 0x8b, 0xf7, 0x7f, 0x08, 0xcb, 0xa9, 0x47,
0x24, 0x58, 0xad, 0xfb, 0xc7, 0xc3, 0x9d, 0xfe, 0xa1, 0x5e, 0x4e, 0x0d, 0xca, 0x3b, 0x07, 0xed,
0xee, 0x21, 0x1e, 0xd4, 0x34, 0xa0, 0x7a, 0xdc, 0x93, 0x9f, 0xf9, 0xf8, 0xf3, 0x17, 0x05, 0xc6,
0xbd, 0xf6, 0xba, 0xe6, 0x60, 0x68, 0x0d, 0x86, 0xed, 0xc7, 0x9d, 0x66, 0x91, 0xa5, 0x95, 0xac,
0xac, 0x74, 0xff, 0x73, 0x58, 0x8c, 0xfb, 0xdd, 0xc7, 0xcf, 0xdf, 0x36, 0x61, 0x7d, 0xbb, 0x33,
0xfc, 0xaa, 0xd3, 0xe9, 0xe1, 0x90, 0xef, 0x74, 0x7a, 0x43, 0xb3, 0x7d, 0xd0, 0x1d, 0x3e, 0x6d,
0xe6, 0xee, 0x7f, 0x01, 0xcd, 0xa4, 0xd3, 0x47, 0xcc, 0x4b, 0xe6, 0x45, 0xee, 0x34, 0xf7, 0xff,
0x43, 0x0e, 0x56, 0xb3, 0x8e, 0x07, 0xd9, 0xc4, 0x14, 0x8c, 0x90, 0xed, 0x94, 0x83, 0x7e, 0xcf,
0xea, 0xf5, 0x31, 0xfc, 0xfb, 0x26, 0xac, 0x27, 0x10, 0xb2, 0x15, 0x39, 0x72, 0x0b, 0x36, 0x52,
0x89, 0x2c, 0xb3, 0x7f, 0x8c, 0x63, 0xd9, 0x82, 0xd5, 0x04, 0xb2, 0x63, 0x9a, 0x7d, 0xb3, 0x59,
0x20, 0xef, 0xc1, 0xbd, 0x04, 0x26, 0x2d, 0x1f, 0x48, 0xf1, 0xa1, 0x48, 0xde, 0x81, 0x37, 0x53,
0xd4, 0xd1, 0x16, 0x6a, 0x6d, 0xb7, 0x0f, 0x58, 0xf3, 0x9a, 0xa5, 0xfb, 0x7f, 0x58, 0x04, 0x88,
0x6e, 0xdb, 0xb2, 0xf2, 0x77, 0xdb, 0xc3, 0xf6, 0x41, 0x9f, 0xad, 0x19, 0xb3, 0x3f, 0x64, 0xb9,
0x9b, 0x9d, 0x1f, 0x34, 0x6f, 0x64, 0x62, 0xfa, 0x47, 0xac, 0x41, 0x1b, 0xb0, 0xc2, 0xe7, 0xdf,
0x01, 0x6b, 0x06, 0x9b, 0x2e, 0xfc, 0x25, 0x01, 0x26, 0x84, 0x1c, 0x1f, 0xed, 0x99, 0xfd, 0xde,
0xd0, 0x1a, 0xec, 0x1f, 0x0f, 0x77, 0xf1, 0x61, 0x82, 0x1d, 0xb3, 0x7b, 0xc4, 0xf3, 0x2c, 0xbe,
0x88, 0x80, 0x65, 0x5d, 0x62, 0x0b, 0xfc, 0x71, 0x7f, 0x30, 0xe8, 0x1e, 0x59, 0x3f, 0x38, 0xee,
0x98, 0xdd, 0xce, 0x00, 0x13, 0x2e, 0x64, 0xc0, 0x19, 0x7d, 0x99, 0xcd, 0xd9, 0xe1, 0xc1, 0x97,
0x62, 0xa3, 0x63, 0xa4, 0x95, 0x38, 0x88, 0x51, 0x55, 0xd9, 0xe8, 0xb0, 0xcd, 0x39, 0x23, 0x67,
0xb8, 0x06, 0xc7, 0xd2, 0xd5, 0xd8, 0x56, 0x9a, 0x5a, 0xf9, 0x98, 0xac, 0x9e, 0x8d, 0x62, 0xa9,
0x50, 0x22, 0x51, 0xf2, 0xdb, 0xee, 0xae, 0x89, 0x09, 0x16, 0x53, 0x50, 0x46, 0xbb, 0xc4, 0x26,
0x21, 0xdb, 0xbd, 0x19, 0x49, 0x53, 0x7e, 0x30, 0xcc, 0x32, 0x6b, 0xf1, 0x57, 0xc7, 0x87, 0xdb,
0x7d, 0x29, 0x06, 0xf0, 0xfa, 0x92, 0x0c, 0x38, 0xa3, 0x5f, 0xc1, 0x97, 0x1f, 0x38, 0x3b, 0x42,
0xc2, 0x55, 0x1d, 0xc0, 0x28, 0xd6, 0x18, 0x13, 0x94, 0x80, 0x9f, 0xef, 0x98, 0x7d, 0x8b, 0xc9,
0x59, 0x28, 0x23, 0x32, 0xfa, 0xf5, 0xeb, 0xd1, 0x2c, 0xf5, 0x06, 0xb2, 0xbb, 0x43, 0x5e, 0xd3,
0xd7, 0xe5, 0x07, 0xc3, 0xdc, 0x79, 0xf8, 0x2f, 0xdf, 0x80, 0xaa, 0xba, 0x8a, 0x43, 0xbe, 0x0f,
0x8d, 0x58, 0xf8, 0x0d, 0x72, 0x2b, 0x3b, 0x28, 0x07, 0xea, 0x57, 0x9b, 0xaf, 0xbd, 0x28, 0x62,
0x07, 0x39, 0xd4, 0x4c, 0x1a, 0x3c, 0xb3, 0xd7, 0x92, 0x66, 0x86, 0x58, 0x6e, 0xb7, 0xaf, 0xc1,
0x8a, 0xec, 0x9e, 0xe0, 0xf3, 0x0b, 0x18, 0xae, 0x52, 0x6c, 0x3c, 0xe4, 0x76, 0x14, 0x0b, 0x5f,
0x87, 0xcb, 0x0c, 0xa5, 0x02, 0xa9, 0xe1, 0x76, 0x69, 0x68, 0x3b, 0x93, 0x80, 0xec, 0x42, 0x4d,
0x7b, 0xd1, 0x98, 0xdc, 0xbc, 0xf6, 0x21, 0xe7, 0xcd, 0xcd, 0x2c, 0x94, 0xa8, 0xd2, 0x77, 0xa1,
0xaa, 0x5e, 0x74, 0x25, 0x1b, 0xda, 0x8b, 0xc3, 0xfa, 0x4b, 0xb8, 0x9b, 0xad, 0x34, 0x42, 0xa4,
0xdf, 0x85, 0x9a, 0xf6, 0xfc, 0xaa, 0xaa, 0x45, 0xfa, 0xf1, 0x57, 0x55, 0x8b, 0xac, 0xd7, 0x5a,
0x0f, 0x60, 0x4d, 0x18, 0x4e, 0x4e, 0xe8, 0xd7, 0xe9, 0x1e, 0x92, 0xee, 0x9e, 0x07, 0x39, 0xf2,
0x05, 0x54, 0xe4, 0xa3, 0xbf, 0x64, 0x3d, 0xfb, 0x11, 0xe5, 0xcd, 0x8d, 0x14, 0x5c, 0x54, 0xa5,
0x0d, 0x10, 0x3d, 0xdf, 0x4a, 0x64, 0xc3, 0x53, 0x0f, 0xc5, 0xaa, 0x91, 0xc9, 0x78, 0xeb, 0x75,
0x17, 0x6a, 0xda, 0x4b, 0xad, 0xaa, 0x4f, 0xd2, 0xaf, 0xbc, 0xaa, 0x3e, 0xc9, 0x7a, 0xd8, 0xf5,
0xfb, 0xd0, 0x88, 0x3d, 0xb9, 0xaa, 0xe6, 0x71, 0xd6, 0x83, 0xae, 0x6a, 0x1e, 0x67, 0xbf, 0xd2,
0xba, 0x0b, 0x35, 0xed, 0x19, 0x54, 0x55, 0xa3, 0xf4, 0x5b, 0xac, 0xaa, 0x46, 0x19, 0xaf, 0xa6,
0xb2, 0xd5, 0x10, 0x7f, 0x03, 0x55, 0xad, 0x86, 0xcc, 0xc7, 0x54, 0xd5, 0x6a, 0xc8, 0x7e, 0x38,
0x95, 0x4d, 0x3d, 0xf5, 0xee, 0x0a, 0xd9, 0x88, 0xd9, 0x2b, 0xa2, 0x07, 0x5c, 0xd4, 0xd4, 0x4b,
0x3f, 0xd1, 0xf2, 0x18, 0x56, 0xd4, 0xa4, 0x51, 0xaf, 0xa6, 0x04, 0xaa, 0x4e, 0x99, 0x6f, 0xb3,
0x6c, 0x36, 0x93, 0xd8, 0x07, 0x39, 0xf2, 0x19, 0x94, 0xc5, 0x53, 0x14, 0x64, 0x2d, 0xf9, 0x34,
0x05, 0xaf, 0xc4, 0x7a, 0xf6, 0x8b, 0x15, 0xe4, 0x08, 0x17, 0xb4, 0xfe, 0x56, 0x84, 0x3e, 0x63,
0x33, 0x9e, 0x97, 0xd8, 0x7c, 0xfd, 0x3a, 0x74, 0x94, 0x63, 0xf2, 0x7d, 0x93, 0xdb, 0xd7, 0x85,
0x11, 0x8b, 0xe7, 0x78, 0x5d, 0xbc, 0xd3, 0xc7, 0x50, 0xd7, 0xdf, 0xbf, 0x23, 0xfa, 0x3a, 0x4c,
0xe6, 0x75, 0x2b, 0x13, 0x27, 0x32, 0xfa, 0x12, 0xd6, 0x55, 0x7f, 0xeb, 0x31, 0xad, 0x02, 0x72,
0x27, 0x23, 0xd2, 0x55, 0xac, 0xd7, 0x6f, 0x5e, 0x1b, 0x0a, 0xeb, 0x41, 0x0e, 0x99, 0x6c, 0xec,
0xc9, 0xaa, 0x88, 0xc9, 0x66, 0xbd, 0xd4, 0x15, 0x31, 0xd9, 0xec, 0x77, 0xae, 0xda, 0xb0, 0xa4,
0xc5, 0xe4, 0x1a, 0x5c, 0xb9, 0x23, 0x35, 0xdf, 0xd3, 0xc1, 0xf9, 0x37, 0xb3, 0xcc, 0xf7, 0x64,
0x07, 0x6a, 0x7a, 0x58, 0xaf, 0x17, 0x24, 0xdf, 0xd0, 0x50, 0x7a, 0xcc, 0xf4, 0x07, 0x39, 0x72,
0x00, 0xcd, 0x64, 0x10, 0x5e, 0xb5, 0x84, 0xb3, 0x02, 0x17, 0x6f, 0x26, 0x90, 0xb1, 0xd0, 0xbd,
0x6c, 0x5e, 0x88, 0xa2, 0xf9, 0x6b, 0xb3, 0x9e, 0x9f, 0xdc, 0x8a, 0x38, 0x5c, 0x76, 0x83, 0xca,
0x2d, 0x81, 0xc5, 0x6a, 0xdf, 0xcb, 0x3d, 0xc8, 0x91, 0x3d, 0xa8, 0xc7, 0x62, 0x50, 0xc6, 0x6e,
0x85, 0x25, 0x9a, 0xd9, 0xd2, 0x71, 0x89, 0x76, 0x1e, 0xc2, 0x62, 0xdc, 0x1d, 0x45, 0x55, 0x2c,
0xd3, 0x67, 0x46, 0x0d, 0x5f, 0xb6, 0x0f, 0x0b, 0xf9, 0x59, 0xa8, 0x31, 0x9e, 0x2c, 0x7d, 0x26,
0x89, 0xc6, 0xa7, 0x93, 0x63, 0xc6, 0x61, 0xc2, 0x9e, 0x5e, 0xf8, 0xab, 0xf9, 0x1c, 0xb6, 0xeb,
0x3b, 0xfc, 0x7d, 0x7d, 0xe9, 0x36, 0xc7, 0xc6, 0xff, 0x55, 0x33, 0x21, 0x7b, 0xbc, 0xf0, 0xa1,
0xc7, 0x83, 0x3d, 0xdc, 0xd4, 0x68, 0x04, 0xec, 0xd5, 0xea, 0xd0, 0xe6, 0x75, 0x10, 0x69, 0x62,
0x73, 0xf0, 0x15, 0xf3, 0x22, 0x9f, 0x02, 0x44, 0xee, 0xca, 0x24, 0xe1, 0x11, 0xab, 0x16, 0x54,
0x86, 0x47, 0x73, 0x87, 0xaf, 0x77, 0xe5, 0x92, 0xab, 0x6f, 0xc9, 0x71, 0xef, 0xe0, 0xd8, 0x96,
0x9c, 0xcc, 0xe6, 0x23, 0x68, 0x1c, 0x78, 0xde, 0xb3, 0xf9, 0x4c, 0x5d, 0xe2, 0x89, 0x3b, 0x84,
0xed, 0xdb, 0xc1, 0xf9, 0x66, 0xa2, 0x5a, 0xa4, 0x0d, 0xcb, 0x8a, 0x45, 0x44, 0x3e, 0xc1, 0x71,
0xa2, 0x18, 0x63, 0x48, 0x64, 0xf0, 0x20, 0x47, 0x1e, 0x42, 0x7d, 0x97, 0x8e, 0x30, 0x4a, 0x0e,
0x3a, 0x08, 0xad, 0xc4, 0x9c, 0x4d, 0xb8, 0x67, 0xd1, 0x66, 0x23, 0x06, 0x94, 0x2c, 0x2e, 0x72,
0x81, 0xd3, 0xf7, 0x8c, 0xb8, 0x1f, 0x59, 0x8c, 0xc5, 0xa5, 0xdc, 0xe0, 0xbe, 0x84, 0xe5, 0x94,
0x1b, 0x98, 0xe2, 0x6e, 0xd7, 0xb9, 0xa6, 0x6d, 0xde, 0xbd, 0x9e, 0x40, 0xe4, 0xfb, 0x3d, 0x68,
0xf0, 0x10, 0xfa, 0x27, 0x94, 0x5f, 0x28, 0x4f, 0x04, 0x48, 0xd4, 0x6f, 0xab, 0x27, 0x59, 0x12,
0x4f, 0xf0, 0x18, 0x1f, 0xf3, 0xd2, 0xae, 0x6b, 0xab, 0x71, 0x4d, 0x5f, 0x21, 0x57, 0xe3, 0x9a,
0x75, 0x33, 0xfc, 0x73, 0xa8, 0x3d, 0xa6, 0xa1, 0xbc, 0x00, 0xad, 0xe4, 0xa3, 0xc4, 0x8d, 0xe8,
0xcd, 0x8c, 0x6b, 0xeb, 0xe4, 0x13, 0x4c, 0xaa, 0x82, 0x79, 0xac, 0x6b, 0xa5, 0xe8, 0x49, 0x97,
0x12, 0x70, 0x26, 0x7d, 0x68, 0x71, 0x86, 0x54, 0xc5, 0xd3, 0x71, 0xa5, 0x54, 0xc5, 0xb3, 0xc2,
0x12, 0xfd, 0x2c, 0xef, 0x01, 0xed, 0xca, 0x75, 0x24, 0x82, 0x25, 0x6f, 0x67, 0xab, 0xea, 0xeb,
0xe4, 0x8f, 0x00, 0x06, 0xa1, 0x37, 0xdb, 0xb5, 0xe9, 0xd4, 0x73, 0x23, 0x9e, 0x10, 0x5d, 0xf6,
0x8d, 0x16, 0xa2, 0x76, 0xe3, 0x97, 0x7c, 0xa5, 0xc9, 0xa6, 0xb1, 0x21, 0x91, 0xc3, 0x7e, 0xed,
0x7d, 0x60, 0xd5, 0x9c, 0x8c, 0x3b, 0xc1, 0xc8, 0x24, 0x20, 0xf2, 0xb2, 0x53, 0x92, 0x66, 0xca,
0x81, 0x4f, 0xad, 0xf5, 0x0c, 0x97, 0xbc, 0xef, 0x42, 0x35, 0x72, 0x4f, 0xda, 0x88, 0x82, 0x9e,
0xc5, 0x9c, 0x99, 0x14, 0xf7, 0x4e, 0xbb, 0x06, 0xf5, 0x60, 0x85, 0x57, 0x47, 0x6d, 0x7f, 0x78,
0x8b, 0x53, 0xbd, 0x45, 0x97, 0xf6, 0xc9, 0x51, 0xeb, 0x27, 0xcb, 0xb3, 0x84, 0xad, 0x9f, 0x94,
0xeb, 0x81, 0x5a, 0x3f, 0xd7, 0xb9, 0x9c, 0xa8, 0xf5, 0x73, 0xbd, 0xd7, 0x42, 0x0f, 0x56, 0x32,
0x9c, 0x08, 0xc8, 0x1b, 0x52, 0xb1, 0xb9, 0xd6, 0xc1, 0x60, 0x33, 0xf3, 0xb0, 0x99, 0x0c, 0x61,
0x83, 0xa7, 0x69, 0x4f, 0x26, 0x89, 0x33, 0xeb, 0xd7, 0xb5, 0x04, 0x19, 0xe7, 0xf0, 0x31, 0x51,
0x26, 0x71, 0x16, 0xdf, 0x83, 0x66, 0xf2, 0xb8, 0x97, 0x5c, 0x4f, 0xbe, 0x79, 0x27, 0x26, 0xb2,
0xa7, 0x8f, 0x88, 0xc9, 0x97, 0xea, 0xd0, 0x39, 0x51, 0xc7, 0x3b, 0xd1, 0x9b, 0xaa, 0x99, 0x47,
0xe4, 0x4a, 0x1b, 0xc8, 0x3c, 0xb3, 0x26, 0x3f, 0x07, 0x1b, 0xc9, 0x19, 0x2d, 0x73, 0xbe, 0x9b,
0xd5, 0x5d, 0xd7, 0x8a, 0x72, 0xf1, 0x06, 0x3d, 0xc8, 0x31, 0x46, 0xac, 0x1f, 0x0d, 0xab, 0x89,
0x94, 0x71, 0x46, 0xad, 0x26, 0x52, 0xe6, 0x59, 0xf2, 0x11, 0x2c, 0x25, 0x4e, 0x85, 0x95, 0x18,
0x9c, 0x7d, 0x8e, 0xac, 0xc4, 0xe0, 0xeb, 0x0e, 0x93, 0x07, 0xd0, 0x4c, 0x9e, 0xf7, 0xaa, 0xb1,
0xbe, 0xe6, 0x0c, 0x79, 0xf3, 0xce, 0xb5, 0xf8, 0x78, 0x35, 0xb5, 0x93, 0xd1, 0x58, 0x35, 0xd3,
0xe7, 0xb9, 0xb1, 0x6a, 0x66, 0x9c, 0xcb, 0x6e, 0xbf, 0xf3, 0xf3, 0xdf, 0x3a, 0x73, 0xc2, 0xf3,
0xf9, 0xc9, 0xd6, 0xc8, 0x9b, 0x7e, 0x30, 0x91, 0x56, 0x0d, 0x11, 0xa1, 0xe1, 0x83, 0x89, 0x3b,
0xfe, 0x00, 0x33, 0x38, 0x59, 0x98, 0xf9, 0x5e, 0xe8, 0x7d, 0xf4, 0xff, 0x02, 0x00, 0x00, 0xff,
0xff, 0x1c, 0xc8, 0x7f, 0x21, 0x38, 0x96, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

2
lnrpc/rpc.proto

@ -3415,6 +3415,8 @@ enum FeatureBit {
ANCHORS_OPT = 21;
ANCHORS_ZERO_FEE_HTLC_REQ = 22;
ANCHORS_ZERO_FEE_HTLC_OPT = 23;
AMP_REQ = 30;
AMP_OPT = 31;
}
message Feature {

8
lnrpc/rpc.swagger.json

@ -1193,7 +1193,9 @@
"ANCHORS_REQ",
"ANCHORS_OPT",
"ANCHORS_ZERO_FEE_HTLC_REQ",
"ANCHORS_ZERO_FEE_HTLC_OPT"
"ANCHORS_ZERO_FEE_HTLC_OPT",
"AMP_REQ",
"AMP_OPT"
]
},
"collectionFormat": "multi"
@ -3559,7 +3561,9 @@
"ANCHORS_REQ",
"ANCHORS_OPT",
"ANCHORS_ZERO_FEE_HTLC_REQ",
"ANCHORS_ZERO_FEE_HTLC_OPT"
"ANCHORS_ZERO_FEE_HTLC_OPT",
"AMP_REQ",
"AMP_OPT"
],
"default": "DATALOSS_PROTECT_REQ"
},

124
lntest/itest/lnd_amp_test.go

@ -7,6 +7,7 @@ import (
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/amp"
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntest"
@ -14,6 +15,129 @@ import (
"github.com/stretchr/testify/require"
)
// testSendPaymentAMP tests that we can send an AMP payment to a specified
// destination using SendPaymentV2.
func testSendPaymentAMP(net *lntest.NetworkHarness, t *harnessTest) {
ctxb := context.Background()
ctx := newMppTestContext(t, net)
defer ctx.shutdownNodes()
const paymentAmt = btcutil.Amount(300000)
// Set up a network with three different paths Alice <-> Bob. Channel
// capacities are set such that the payment can only succeed if (at
// least) three paths are used.
//
// _ Eve _
// / \
// Alice -- Carol ---- Bob
// \ /
// \__ Dave ____/
//
ctx.openChannel(ctx.carol, ctx.bob, 135000)
ctx.openChannel(ctx.alice, ctx.carol, 235000)
ctx.openChannel(ctx.dave, ctx.bob, 135000)
ctx.openChannel(ctx.alice, ctx.dave, 135000)
ctx.openChannel(ctx.eve, ctx.bob, 135000)
ctx.openChannel(ctx.carol, ctx.eve, 135000)
defer ctx.closeChannels()
ctx.waitForChannels()
// Increase Dave's fee to make the test deterministic. Otherwise it
// would be unpredictable whether pathfinding would go through Charlie
// or Dave for the first shard.
_, err := ctx.dave.UpdateChannelPolicy(
context.Background(),
&lnrpc.PolicyUpdateRequest{
Scope: &lnrpc.PolicyUpdateRequest_Global{Global: true},
BaseFeeMsat: 500000,
FeeRate: 0.001,
TimeLockDelta: 40,
},
)
if err != nil {
t.Fatalf("dave policy update: %v", err)
}
ctxt, _ := context.WithTimeout(context.Background(), 4*defaultTimeout)
payment := sendAndAssertSuccess(
ctxt, t, net.Alice,
&routerrpc.SendPaymentRequest{
Dest: net.Bob.PubKey[:],
Amt: int64(paymentAmt),
FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta,
MaxParts: 10,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
Amp: true,
},
)
// Check that Alice split the payment in at least three shards. Because
// the hand-off of the htlc to the link is asynchronous (via a mailbox),
// there is some non-determinism in the process. Depending on whether
// the new pathfinding round is started before or after the htlc is
// locked into the channel, different sharding may occur. Therefore we
// can only check if the number of shards isn't below the theoretical
// minimum.
succeeded := 0
for _, htlc := range payment.Htlcs {
if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED {
succeeded++
}
}
const minExpectedShards = 3
if succeeded < minExpectedShards {
t.Fatalf("expected at least %v shards, but got %v",
minExpectedShards, succeeded)
}
// Fetch Bob's invoices.
invoiceResp, err := net.Bob.ListInvoices(
ctxb, &lnrpc.ListInvoiceRequest{},
)
require.NoError(t.t, err)
// There should only be one invoice.
require.Equal(t.t, 1, len(invoiceResp.Invoices))
rpcInvoice := invoiceResp.Invoices[0]
// Assert that the invoice is settled for the total payment amount and
// has the correct payment address.
require.True(t.t, rpcInvoice.Settled)
require.Equal(t.t, lnrpc.Invoice_SETTLED, rpcInvoice.State)
require.Equal(t.t, int64(paymentAmt), rpcInvoice.AmtPaidSat)
require.Equal(t.t, int64(paymentAmt*1000), rpcInvoice.AmtPaidMsat)
// Finally, assert that the same set id is recorded for each htlc, and
// that the preimage hash pair is valid.
var setID []byte
require.Equal(t.t, succeeded, len(rpcInvoice.Htlcs))
for _, htlc := range rpcInvoice.Htlcs {
require.NotNil(t.t, htlc.Amp)
if setID == nil {
setID = make([]byte, 32)
copy(setID, htlc.Amp.SetId)
}
require.Equal(t.t, setID, htlc.Amp.SetId)
// Parse the child hash and child preimage, and assert they are
// well-formed.
childHash, err := lntypes.MakeHash(htlc.Amp.Hash)
require.NoError(t.t, err)
childPreimage, err := lntypes.MakePreimage(htlc.Amp.Preimage)
require.NoError(t.t, err)
// Assert that the preimage actually matches the hashes.
validPreimage := childPreimage.Matches(childHash)
require.True(t.t, validPreimage)
}
}
func testSendToRouteAMP(net *lntest.NetworkHarness, t *harnessTest) {
ctxb := context.Background()

4
lntest/itest/lnd_multi-hop-error-propagation_test.go

@ -296,8 +296,10 @@ out:
if err != nil {
t.Fatalf("unable to generate carol invoice: %v", err)
}
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
sendAndAssertSuccess(
t, net.Bob,
ctxt, t, net.Bob,
&routerrpc.SendPaymentRequest{
PaymentRequest: carolInvoice2.PaymentRequest,
TimeoutSeconds: 60,

5
lntest/itest/lnd_send_multi_path_payment_test.go

@ -68,8 +68,9 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) {
rHash := rHashes[0]
payReq := payReqs[0]
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
payment := sendAndAssertSuccess(
t, net.Alice,
ctxt, t, net.Alice,
&routerrpc.SendPaymentRequest{
PaymentRequest: payReq,
MaxParts: 10,
@ -105,7 +106,7 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) {
// Make sure Bob show the invoice as settled for the full
// amount.
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
inv, err := ctx.bob.LookupInvoice(
ctxt, &lnrpc.PaymentHash{
RHash: rHash,

9
lntest/itest/lnd_single_hop_invoice_test.go

@ -63,8 +63,9 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
// With the invoice for Bob added, send a payment towards Alice paying
// to the above generated invoice.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
resp := sendAndAssertSuccess(
t, net.Alice,
ctxt, t, net.Alice,
&routerrpc.SendPaymentRequest{
PaymentRequest: invoiceResp.PaymentRequest,
TimeoutSeconds: 60,
@ -115,8 +116,9 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
// Next send another payment, but this time using a zpay32 encoded
// invoice rather than manually specifying the payment details.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
sendAndAssertSuccess(
t, net.Alice,
ctxt, t, net.Alice,
&routerrpc.SendPaymentRequest{
PaymentRequest: invoiceResp.PaymentRequest,
TimeoutSeconds: 60,
@ -138,8 +140,9 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
keySendPreimage := lntypes.Preimage{3, 4, 5, 11}
keySendHash := keySendPreimage.Hash()
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
sendAndAssertSuccess(
t, net.Alice,
ctxt, t, net.Alice,
&routerrpc.SendPaymentRequest{
Dest: net.Bob.PubKey[:],
Amt: paymentAmt,

24
lntest/itest/lnd_test.go

@ -1300,11 +1300,14 @@ func testPaymentFollowingChannelOpen(net *lntest.NetworkHarness, t *harnessTest)
// Send payment to Bob so that a channel update to disk will be
// executed.
sendAndAssertSuccess(t, net.Alice, &routerrpc.SendPaymentRequest{
PaymentRequest: bobPayReqs[0],
TimeoutSeconds: 60,
FeeLimitSat: 1000000,
})
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
sendAndAssertSuccess(
ctxt, t, net.Alice, &routerrpc.SendPaymentRequest{
PaymentRequest: bobPayReqs[0],
TimeoutSeconds: 60,
FeeLimitSat: 1000000,
},
)
// At this point we want to make sure the channel is opened and not
// pending.
@ -5216,8 +5219,9 @@ func testListPayments(net *lntest.NetworkHarness, t *harnessTest) {
// With the invoice for Bob added, send a payment towards Alice paying
// to the above generated invoice.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
sendAndAssertSuccess(
t, net.Alice,
ctxt, t, net.Alice,
&routerrpc.SendPaymentRequest{
PaymentRequest: invoiceResp.PaymentRequest,
TimeoutSeconds: 60,
@ -13095,7 +13099,8 @@ func testRouteFeeCutoff(net *lntest.NetworkHarness, t *harnessTest) {
sendReq.FeeLimitMsat = 1000 * paymentAmt * limit.Percent / 100
}
result := sendAndAssertSuccess(t, net.Alice, sendReq)
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
result := sendAndAssertSuccess(ctxt, t, net.Alice, sendReq)
checkRoute(result.Htlcs[0].Route)
}
@ -13884,12 +13889,9 @@ func deriveFundingShim(net *lntest.NetworkHarness, t *harnessTest,
// sendAndAssertSuccess sends the given payment requests and asserts that the
// payment completes successfully.
func sendAndAssertSuccess(t *harnessTest, node *lntest.HarnessNode,
func sendAndAssertSuccess(ctx context.Context, t *harnessTest, node *lntest.HarnessNode,
req *routerrpc.SendPaymentRequest) *lnrpc.Payment {
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel()
var result *lnrpc.Payment
err := wait.NoError(func() error {
stream, err := node.RouterClient.SendPaymentV2(ctx, req)

5
lntest/itest/lnd_test_list_on_test.go

@ -274,6 +274,11 @@ var allTestCases = []*testCase{
name: "sendtoroute amp",
test: testSendToRouteAMP,
},
{
name: "sendpayment amp",
test: testSendPaymentAMP,
},
{
name: "send multi path payment",
test: testSendMultiPathPayment,

20
lntest/itest/log_error_whitelist.txt

@ -36,16 +36,16 @@
<time> [ERR] CRTR: Failed sending attempt <number> for payment <hex> to switch: insufficient bandwidth to route htlc
<time> [ERR] CRTR: Failed sending attempt <number> for payment <hex> to switch: UnknownNextPeer
<time> [ERR] CRTR: out of order block: expecting height=<height>, got height=<height>
<time> [ERR] CRTR: Payment with hash <hex> failed: error
<time> [ERR] CRTR: Payment with hash <hex> failed: incorrect_payment_details
<time> [ERR] CRTR: Payment with hash <hex> failed: insufficient_balance
<time> [ERR] CRTR: Payment with hash <hex> failed: no_route
<time> [ERR] CRTR: Payment with hash <hex> failed: router shutting down
<time> [ERR] CRTR: Payment with hash <hex> failed: timeout
<time> [ERR] CRTR: Resuming payment with hash <hex> failed: error.
<time> [ERR] CRTR: Resuming payment with hash <hex> failed: incorrect_payment_details.
<time> [ERR] CRTR: Resuming payment with hash <hex> failed: no_route.
<time> [ERR] CRTR: Resuming payment with hash <hex> failed: router shutting down.
<time> [ERR] CRTR: Payment <hex> failed: error
<time> [ERR] CRTR: Payment <hex> failed: incorrect_payment_details
<time> [ERR] CRTR: Payment <hex> failed: insufficient_balance
<time> [ERR] CRTR: Payment <hex> failed: no_route
<time> [ERR] CRTR: Payment <hex> failed: router shutting down
<time> [ERR] CRTR: Payment <hex> failed: timeout
<time> [ERR] CRTR: Resuming payment <hex> failed: error.
<time> [ERR] CRTR: Resuming payment <hex> failed: incorrect_payment_details.
<time> [ERR] CRTR: Resuming payment <hex> failed: no_route.
<time> [ERR] CRTR: Resuming payment <hex> failed: router shutting down.
<time> [ERR] CRTR: unable to add channel: edge not found
<time> [ERR] CRTR: Unable to retrieve channel by id: edge not found
<time> [ERR] DISC: channel announcement proof for short_chan_id=<cid> isn't valid: can't verify first bitcoin signature

4
routing/control_tower.go

@ -50,7 +50,7 @@ type ControlTower interface {
Fail(lntypes.Hash, channeldb.FailureReason) error
// FetchInFlightPayments returns all payments with status InFlight.
FetchInFlightPayments() ([]*channeldb.InFlightPayment, error)
FetchInFlightPayments() ([]*channeldb.MPPayment, error)
// SubscribePayment subscribes to updates for the payment with the given
// hash. A first update with the current state of the payment is always
@ -213,7 +213,7 @@ func (p *controlTower) Fail(paymentHash lntypes.Hash,
}
// FetchInFlightPayments returns all payments with status InFlight.
func (p *controlTower) FetchInFlightPayments() ([]*channeldb.InFlightPayment, error) {
func (p *controlTower) FetchInFlightPayments() ([]*channeldb.MPPayment, error) {
return p.db.FetchInFlightPayments()
}

32
routing/control_tower_test.go

@ -79,26 +79,26 @@ func TestControlTowerSubscribeSuccess(t *testing.T) {
t.Fatal(err)
}
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatal(err)
}
// Subscription should succeed and immediately report the InFlight
// status.
subscriber1, err := pControl.SubscribePayment(info.PaymentHash)
subscriber1, err := pControl.SubscribePayment(info.PaymentIdentifier)
if err != nil {
t.Fatalf("expected subscribe to succeed, but got: %v", err)
}
// Register an attempt.
err = pControl.RegisterAttempt(info.PaymentHash, attempt)
err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatal(err)
}
// Register a second subscriber after the first attempt has started.
subscriber2, err := pControl.SubscribePayment(info.PaymentHash)
subscriber2, err := pControl.SubscribePayment(info.PaymentIdentifier)
if err != nil {
t.Fatalf("expected subscribe to succeed, but got: %v", err)
}
@ -108,7 +108,7 @@ func TestControlTowerSubscribeSuccess(t *testing.T) {
Preimage: preimg,
}
htlcAttempt, err := pControl.SettleAttempt(
info.PaymentHash, attempt.AttemptID, &settleInfo,
info.PaymentIdentifier, attempt.AttemptID, &settleInfo,
)
if err != nil {
t.Fatal(err)
@ -118,7 +118,7 @@ func TestControlTowerSubscribeSuccess(t *testing.T) {
}
// Register a third subscriber after the payment succeeded.
subscriber3, err := pControl.SubscribePayment(info.PaymentHash)
subscriber3, err := pControl.SubscribePayment(info.PaymentIdentifier)
if err != nil {
t.Fatalf("expected subscribe to succeed, but got: %v", err)
}
@ -196,13 +196,13 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) {
t.Fatal(err)
}
err = pControl.InitPayment(info.PaymentHash, info)
err = pControl.InitPayment(info.PaymentIdentifier, info)
if err != nil {
t.Fatal(err)
}
// Subscription should succeed.
subscriber1, err := pControl.SubscribePayment(info.PaymentHash)
subscriber1, err := pControl.SubscribePayment(info.PaymentIdentifier)
if err != nil {
t.Fatalf("expected subscribe to succeed, but got: %v", err)
}
@ -212,7 +212,7 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) {
// making any attempts at all.
if registerAttempt {
// Register an attempt.
err = pControl.RegisterAttempt(info.PaymentHash, attempt)
err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
if err != nil {
t.Fatal(err)
}
@ -222,7 +222,7 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) {
Reason: channeldb.HTLCFailInternal,
}
htlcAttempt, err := pControl.FailAttempt(
info.PaymentHash, attempt.AttemptID, &failInfo,
info.PaymentIdentifier, attempt.AttemptID, &failInfo,
)
if err != nil {
t.Fatalf("unable to fail htlc: %v", err)
@ -233,12 +233,12 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) {
}
// Mark the payment as failed.
if err := pControl.Fail(info.PaymentHash, channeldb.FailureReasonTimeout); err != nil {
if err := pControl.Fail(info.PaymentIdentifier, channeldb.FailureReasonTimeout); err != nil {
t.Fatal(err)
}
// Register a second subscriber after the payment failed.
subscriber2, err := pControl.SubscribePayment(info.PaymentHash)
subscriber2, err := pControl.SubscribePayment(info.PaymentIdentifier)
if err != nil {
t.Fatalf("expected subscribe to succeed, but got: %v", err)
}
@ -326,10 +326,10 @@ func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.HTLCAttemptInfo,
rhash := sha256.Sum256(preimage[:])
return &channeldb.PaymentCreationInfo{
PaymentHash: rhash,
Value: testRoute.ReceiverAmt(),
CreationTime: time.Unix(time.Now().Unix(), 0),
PaymentRequest: []byte("hola"),
PaymentIdentifier: rhash,
Value: testRoute.ReceiverAmt(),
CreationTime: time.Unix(time.Now().Unix(), 0),
PaymentRequest: []byte("hola"),
},
&channeldb.HTLCAttemptInfo{
AttemptID: 1,

5
routing/integrated_routing_context_test.go

@ -152,6 +152,11 @@ func (c *integratedRoutingContext) testPayment(maxParts uint32,
MaxParts: maxParts,
}
var paymentHash [32]byte
if err := payment.SetPaymentHash(paymentHash); err != nil {
return nil, err
}
if c.maxShardAmt != nil {
payment.MaxShardAmt = c.maxShardAmt
}

20
routing/mock_test.go

@ -452,6 +452,12 @@ func (m *mockControlTower) FetchPayment(phash lntypes.Hash) (
m.Lock()
defer m.Unlock()
return m.fetchPayment(phash)
}
func (m *mockControlTower) fetchPayment(phash lntypes.Hash) (
*channeldb.MPPayment, error) {
p, ok := m.payments[phash]
if !ok {
return nil, channeldb.ErrPaymentNotInitiated
@ -468,12 +474,11 @@ func (m *mockControlTower) FetchPayment(phash lntypes.Hash) (
// Return a copy of the current attempts.
mp.HTLCs = append(mp.HTLCs, p.attempts...)
return mp, nil
}
func (m *mockControlTower) FetchInFlightPayments() (
[]*channeldb.InFlightPayment, error) {
[]*channeldb.MPPayment, error) {
if m.fetchInFlight != nil {
m.fetchInFlight <- struct{}{}
@ -483,8 +488,8 @@ func (m *mockControlTower) FetchInFlightPayments() (
defer m.Unlock()
// In flight are all payments not successful or failed.
var fl []*channeldb.InFlightPayment
for hash, p := range m.payments {
var fl []*channeldb.MPPayment
for hash := range m.payments {
if _, ok := m.successful[hash]; ok {
continue
}
@ -492,11 +497,12 @@ func (m *mockControlTower) FetchInFlightPayments() (
continue
}
ifl := channeldb.InFlightPayment{
Info: &p.info,
mp, err := m.fetchPayment(hash)
if err != nil {
return nil, err
}
fl = append(fl, &ifl)
fl = append(fl, mp)
}
return fl, nil

2
routing/pathfind.go

@ -194,6 +194,8 @@ func newRoute(sourceVertex route.Vertex,
}
// Otherwise attach the mpp record if it exists.
// TODO(halseth): move this to payment life cycle,
// where AMP options are set.
if finalHop.paymentAddr != nil {
mpp = record.NewMPP(
finalHop.totalAmt,

158
routing/payment_lifecycle.go

@ -12,6 +12,7 @@ import (
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/routing/shards"
)
// errShardHandlerExiting is returned from the shardHandler when it exits.
@ -23,8 +24,9 @@ type paymentLifecycle struct {
router *ChannelRouter
totalAmount lnwire.MilliSatoshi
feeLimit lnwire.MilliSatoshi
paymentHash lntypes.Hash
identifier lntypes.Hash
paySession PaymentSession
shardTracker shards.ShardTracker
timeoutChan <-chan time.Time
currentHeight int32
}
@ -83,10 +85,11 @@ func (p *paymentLifecycle) paymentState(payment *channeldb.MPPayment) (
// resumePayment resumes the paymentLifecycle from the current state.
func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) {
shardHandler := &shardHandler{
router: p.router,
paymentHash: p.paymentHash,
shardErrors: make(chan error),
quit: make(chan struct{}),
router: p.router,
identifier: p.identifier,
shardTracker: p.shardTracker,
shardErrors: make(chan error),
quit: make(chan struct{}),
}
// When the payment lifecycle loop exits, we make sure to signal any
@ -98,7 +101,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) {
// up goroutines that'll collect their results and deliver them to the
// lifecycle loop below.
payment, err := p.router.cfg.Control.FetchPayment(
p.paymentHash,
p.identifier,
)
if err != nil {
return [32]byte{}, nil, err
@ -107,8 +110,8 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) {
for _, a := range payment.InFlightHTLCs() {
a := a
log.Infof("Resuming payment shard %v for hash %v",
a.AttemptID, p.paymentHash)
log.Infof("Resuming payment shard %v for payment %v",
a.AttemptID, p.identifier)
shardHandler.collectResultAsync(&a.HTLCAttemptInfo)
}
@ -128,7 +131,7 @@ lifecycle:
// act on the latest available information, whether we are
// resuming an existing payment or just sent a new attempt.
payment, err := p.router.cfg.Control.FetchPayment(
p.paymentHash,
p.identifier,
)
if err != nil {
return [32]byte{}, nil, err
@ -143,7 +146,7 @@ lifecycle:
log.Debugf("Payment %v in state terminate=%v, "+
"active_shards=%v, rem_value=%v, fee_limit=%v",
p.paymentHash, state.terminate, state.numShardsInFlight,
p.identifier, state.terminate, state.numShardsInFlight,
state.remainingAmt, state.remainingFees)
switch {
@ -190,7 +193,7 @@ lifecycle:
// return with an error the moment all active shards
// have finished.
saveErr := p.router.cfg.Control.Fail(
p.paymentHash, channeldb.FailureReasonTimeout,
p.identifier, channeldb.FailureReasonTimeout,
)
if saveErr != nil {
return [32]byte{}, nil, saveErr
@ -212,7 +215,7 @@ lifecycle:
)
if err != nil {
log.Warnf("Failed to find route for payment %v: %v",
p.paymentHash, err)
p.identifier, err)
routeErr, ok := err.(noRouteError)
if !ok {
@ -226,10 +229,10 @@ lifecycle:
failureCode := routeErr.FailureReason()
log.Debugf("Marking payment %v permanently "+
"failed with no route: %v",
p.paymentHash, failureCode)
p.identifier, failureCode)
saveErr := p.router.cfg.Control.Fail(
p.paymentHash, failureCode,
p.identifier, failureCode,
)
if saveErr != nil {
return [32]byte{}, nil, saveErr
@ -246,16 +249,20 @@ lifecycle:
continue lifecycle
}
// If this route will consume the last remeining amount to send
// to the receiver, this will be our last shard (for now).
lastShard := rt.ReceiverAmt() == state.remainingAmt
// We found a route to try, launch a new shard.
attempt, outcome, err := shardHandler.launchShard(rt)
attempt, outcome, err := shardHandler.launchShard(rt, lastShard)
switch {
// We may get a terminal error if we've processed a shard with
// a terminal state (settled or permanent failure), while we
// were pathfinding. We know we're in a terminal state here,
// so we can continue and wait for our last shards to return.
case err == channeldb.ErrPaymentTerminal:
log.Infof("Payment: %v in terminal state, abandoning "+
"shard", p.paymentHash)
log.Infof("Payment %v in terminal state, abandoning "+
"shard", p.identifier)
continue lifecycle
@ -268,7 +275,7 @@ lifecycle:
if outcome.err != nil {
log.Warnf("Failed to launch shard %v for "+
"payment %v: %v", attempt.AttemptID,
p.paymentHash, outcome.err)
p.identifier, outcome.err)
// We must inspect the error to know whether it was
// critical or not, to decide whether we should
@ -294,8 +301,9 @@ lifecycle:
// shardHandler holds what is necessary to send and collect the result of
// shards.
type shardHandler struct {
paymentHash lntypes.Hash
router *ChannelRouter
identifier lntypes.Hash
router *ChannelRouter
shardTracker shards.ShardTracker
// shardErrors is a channel where errors collected by calling
// collectResultAsync will be delivered. These results are meant to be
@ -366,19 +374,20 @@ type launchOutcome struct {
}
// launchShard creates and sends an HTLC attempt along the given route,
// registering it with the control tower before sending it. It returns the
// HTLCAttemptInfo that was created for the shard, along with a launchOutcome.
// The launchOutcome is used to indicate whether the attempt was successfully
// sent. If the launchOutcome wraps a non-nil error, it means that the attempt
// was not sent onto the network, so no result will be available in the future
// for it.
func (p *shardHandler) launchShard(rt *route.Route) (*channeldb.HTLCAttemptInfo,
*launchOutcome, error) {
// registering it with the control tower before sending it. The lastShard
// argument should be true if this shard will consume the remainder of the
// amount to send. It returns the HTLCAttemptInfo that was created for the
// shard, along with a launchOutcome. The launchOutcome is used to indicate
// whether the attempt was successfully sent. If the launchOutcome wraps a
// non-nil error, it means that the attempt was not sent onto the network, so
// no result will be available in the future for it.
func (p *shardHandler) launchShard(rt *route.Route,
lastShard bool) (*channeldb.HTLCAttemptInfo, *launchOutcome, error) {
// Using the route received from the payment session, create a new
// shard to send.
firstHop, htlcAdd, attempt, err := p.createNewPaymentAttempt(
rt,
rt, lastShard,
)
if err != nil {
return nil, nil, err
@ -389,7 +398,7 @@ func (p *shardHandler) launchShard(rt *route.Route) (*channeldb.HTLCAttemptInfo,
// of the payment that we attempted to send, such that we can query the
// Switch for its whereabouts. The route is needed to handle the result
// when it eventually comes back.
err = p.router.cfg.Control.RegisterAttempt(p.paymentHash, attempt)
err = p.router.cfg.Control.RegisterAttempt(p.identifier, attempt)
if err != nil {
return nil, nil, err
}
@ -441,7 +450,7 @@ func (p *shardHandler) collectResultAsync(attempt *channeldb.HTLCAttemptInfo) {
log.Errorf("Error collecting result for "+
"shard %v for payment %v: %v",
attempt.AttemptID, p.paymentHash, err)
attempt.AttemptID, p.identifier, err)
}
select {
@ -480,10 +489,17 @@ func (p *shardHandler) collectResultAsync(attempt *channeldb.HTLCAttemptInfo) {
func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
*shardResult, error) {
// We'll retrieve the hash specific to this shard from the
// shardTracker, since it will be needed to regenerate the circuit
// below.
hash, err := p.shardTracker.GetHash(attempt.AttemptID)
if err != nil {
return nil, err
}
// Regenerate the circuit for this attempt.
_, circuit, err := generateSphinxPacket(
&attempt.Route, p.paymentHash[:],
attempt.SessionKey,
&attempt.Route, hash[:], attempt.SessionKey,
)
if err != nil {
return nil, err
@ -499,7 +515,7 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
// Now ask the switch to return the result of the payment when
// available.
resultChan, err := p.router.cfg.Payer.GetPaymentResult(
attempt.AttemptID, p.paymentHash, errorDecryptor,
attempt.AttemptID, p.identifier, errorDecryptor,
)
switch {
@ -508,9 +524,9 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
// case we can safely send a new payment attempt, and wait for its
// result to be available.
case err == htlcswitch.ErrPaymentIDNotFound:
log.Debugf("Payment ID %v for hash %v not found in "+
log.Debugf("Attempt ID %v for payment %v not found in "+
"the Switch, retrying.", attempt.AttemptID,
p.paymentHash)
p.identifier)
attempt, cErr := p.failAttempt(attempt, err)
if cErr != nil {
@ -566,7 +582,7 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
// We successfully got a payment result back from the switch.
log.Debugf("Payment %v succeeded with pid=%v",
p.paymentHash, attempt.AttemptID)
p.identifier, attempt.AttemptID)
// Report success to mission control.
err = p.router.cfg.MissionControl.ReportPaymentSuccess(
@ -580,7 +596,7 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
// In case of success we atomically store settle result to the DB move
// the shard to the settled state.
htlcAttempt, err := p.router.cfg.Control.SettleAttempt(
p.paymentHash, attempt.AttemptID,
p.identifier, attempt.AttemptID,
&channeldb.HTLCSettleInfo{
Preimage: result.Preimage,
SettleTime: p.router.cfg.Clock.Now(),
@ -597,7 +613,7 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
}
// createNewPaymentAttempt creates a new payment attempt from the given route.
func (p *shardHandler) createNewPaymentAttempt(rt *route.Route) (
func (p *shardHandler) createNewPaymentAttempt(rt *route.Route, lastShard bool) (
lnwire.ShortChannelID, *lnwire.UpdateAddHTLC,
*channeldb.HTLCAttemptInfo, error) {
@ -607,12 +623,39 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route) (
return lnwire.ShortChannelID{}, nil, nil, err
}
// We generate a new, unique payment ID that we will use for
// this HTLC.
attemptID, err := p.router.cfg.NextPaymentID()
if err != nil {
return lnwire.ShortChannelID{}, nil, nil, err
}
// Requesst a new shard from the ShardTracker. If this is an AMP
// payment, and this is the last shard, the outstanding shards together
// with ths one will be enough for the receiver to derive all HTLC
// preimages. If this a non-AMP payment, the ShardTracker will return a
// simple shard with the payment's static payment hash.
shard, err := p.shardTracker.NewShard(attemptID, lastShard)
if err != nil {
return lnwire.ShortChannelID{}, nil, nil, err
}
// It this shard carries MPP or AMP options, add them to the last hop
// on the route.
hop := rt.Hops[len(rt.Hops)-1]
if shard.MPP() != nil {
hop.MPP = shard.MPP()
}
if shard.AMP() != nil {
hop.AMP = shard.AMP()
}
// Generate the raw encoded sphinx packet to be included along
// with the htlcAdd message that we send directly to the
// switch.
onionBlob, _, err := generateSphinxPacket(
rt, p.paymentHash[:], sessionKey,
)
hash := shard.Hash()
onionBlob, _, err := generateSphinxPacket(rt, hash[:], sessionKey)
if err != nil {
return lnwire.ShortChannelID{}, nil, nil, err
}
@ -623,7 +666,7 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route) (
htlcAdd := &lnwire.UpdateAddHTLC{
Amount: rt.TotalAmount,
Expiry: rt.TotalTimeLock,
PaymentHash: p.paymentHash,
PaymentHash: hash,
}
copy(htlcAdd.OnionBlob[:], onionBlob)
@ -634,13 +677,6 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route) (
rt.Hops[0].ChannelID,
)
// We generate a new, unique payment ID that we will use for
// this HTLC.
attemptID, err := p.router.cfg.NextPaymentID()
if err != nil {
return lnwire.ShortChannelID{}, nil, nil, err
}
// We now have all the information needed to populate
// the current attempt information.
attempt := &channeldb.HTLCAttemptInfo{
@ -648,6 +684,7 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route) (
AttemptTime: p.router.cfg.Clock.Now(),
SessionKey: sessionKey,
Route: *rt,
Hash: &hash,
}
return firstHop, htlcAdd, attempt, nil
@ -659,7 +696,7 @@ func (p *shardHandler) sendPaymentAttempt(
htlcAdd *lnwire.UpdateAddHTLC) error {
log.Tracef("Attempting to send payment %v (pid=%v), "+
"using route: %v", p.paymentHash, attempt.AttemptID,
"using route: %v", p.identifier, attempt.AttemptID,
newLogClosure(func() string {
return spew.Sdump(attempt.Route)
}),
@ -675,12 +712,12 @@ func (p *shardHandler) sendPaymentAttempt(
if err != nil {
log.Errorf("Failed sending attempt %d for payment "+
"%v to switch: %v", attempt.AttemptID,
p.paymentHash, err)
p.identifier, err)
return err
}
log.Debugf("Payment %v (pid=%v) successfully sent to switch, route: %v",
p.paymentHash, attempt.AttemptID, &attempt.Route)
p.identifier, attempt.AttemptID, &attempt.Route)
return nil
}
@ -700,9 +737,9 @@ func (p *shardHandler) handleSendError(attempt *channeldb.HTLCAttemptInfo,
}
log.Infof("Payment %v failed: final_outcome=%v, raw_err=%v",
p.paymentHash, *reason, sendErr)
p.identifier, *reason, sendErr)
err := p.router.cfg.Control.Fail(p.paymentHash, *reason)
err := p.router.cfg.Control.Fail(p.identifier, *reason)
if err != nil {
return err
}
@ -715,15 +752,22 @@ func (p *shardHandler) failAttempt(attempt *channeldb.HTLCAttemptInfo,
sendError error) (*channeldb.HTLCAttempt, error) {
log.Warnf("Attempt %v for payment %v failed: %v", attempt.AttemptID,
p.paymentHash, sendError)
p.identifier, sendError)
failInfo := marshallError(
sendError,
p.router.cfg.Clock.Now(),
)
// Now that we are failing this payment attempt, cancel the shard with
// the ShardTracker such that it can derive the correct hash for the
// next attempt.
if err := p.shardTracker.CancelShard(attempt.AttemptID); err != nil {
return nil, err
}
return p.router.cfg.Control.FailAttempt(
p.paymentHash, attempt.AttemptID,
p.identifier, attempt.AttemptID,
failInfo,
)
}

2
routing/payment_lifecycle_test.go

@ -815,7 +815,7 @@ func testPaymentLifecycle(t *testing.T, test paymentLifecycleTestCase,
Target: testGraph.aliasMap["c"],
Amount: paymentAmt,
FeeLimit: noFeeLimit,
PaymentHash: payHash,
paymentHash: &payHash,
}
// Setup our payment session source to block on release of

2
routing/payment_session.go

@ -171,7 +171,7 @@ func newPaymentSession(p *LightningPayment,
return nil, err
}
logPrefix := fmt.Sprintf("PaymentSession(%x):", p.PaymentHash)
logPrefix := fmt.Sprintf("PaymentSession(%x):", p.Identifier())
return &paymentSession{
additionalEdges: edges,

5
routing/payment_session_test.go

@ -23,6 +23,11 @@ func TestRequestRoute(t *testing.T) {
FeeLimit: 1000,
}
var paymentHash [32]byte
if err := payment.SetPaymentHash(paymentHash); err != nil {
t.Fatal(err)
}
session, err := newPaymentSession(
payment,
func() (map[uint64]lnwire.MilliSatoshi,

243
routing/router.go

@ -15,6 +15,7 @@ import (
"github.com/go-errors/errors"
sphinx "github.com/lightningnetwork/lightning-onion"
"github.com/lightningnetwork/lnd/amp"
"github.com/lightningnetwork/lnd/batch"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channeldb/kvdb"
@ -29,6 +30,7 @@ import (
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/chainview"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/routing/shards"
"github.com/lightningnetwork/lnd/ticker"
"github.com/lightningnetwork/lnd/zpay32"
)
@ -165,17 +167,21 @@ type PaymentAttemptDispatcher interface {
// denoted by its public key. A non-nil error is to be returned if the
// payment was unsuccessful.
SendHTLC(firstHop lnwire.ShortChannelID,
paymentID uint64,
attemptID uint64,
htlcAdd *lnwire.UpdateAddHTLC) error
// GetPaymentResult returns the the result of the payment attempt with
// the given paymentID. The method returns a channel where the payment
// result will be sent when available, or an error is encountered
// during forwarding. When a result is received on the channel, the
// HTLC is guaranteed to no longer be in flight. The switch shutting
// down is signaled by closing the channel. If the paymentID is
// unknown, ErrPaymentIDNotFound will be returned.
GetPaymentResult(paymentID uint64, paymentHash lntypes.Hash,
// the given attemptID. The paymentHash should be set to the payment's
// overall hash, or in case of AMP payments the payment's unique
// identifier.
//
// The method returns a channel where the payment result will be sent
// when available, or an error is encountered during forwarding. When a
// result is received on the channel, the HTLC is guaranteed to no
// longer be in flight. The switch shutting down is signaled by
// closing the channel. If the attemptID is unknown,
// ErrPaymentIDNotFound will be returned.
GetPaymentResult(attemptID uint64, paymentHash lntypes.Hash,
deobfuscator htlcswitch.ErrorDecrypter) (
<-chan *htlcswitch.PaymentResult, error)
@ -211,13 +217,13 @@ type MissionController interface {
// input for future probability estimates. It returns a bool indicating
// whether this error is a final error and no further payment attempts
// need to be made.
ReportPaymentFail(paymentID uint64, rt *route.Route,
ReportPaymentFail(attemptID uint64, rt *route.Route,
failureSourceIdx *int, failure lnwire.FailureMessage) (
*channeldb.FailureReason, error)
// ReportPaymentSuccess reports a successful payment to mission control as input
// for future probability estimates.
ReportPaymentSuccess(paymentID uint64, rt *route.Route) error
ReportPaymentSuccess(attemptID uint64, rt *route.Route) error
// GetProbability is expected to return the success probability of a
// payment from fromNode along edge.
@ -583,14 +589,7 @@ func (r *ChannelRouter) Start() error {
// until the cleaning has finished.
toKeep := make(map[uint64]struct{})
for _, p := range payments {
payment, err := r.cfg.Control.FetchPayment(
p.Info.PaymentHash,
)
if err != nil {
return err
}
for _, a := range payment.HTLCs {
for _, a := range p.HTLCs {
toKeep[a.AttemptID] = struct{}{}
}
}
@ -601,11 +600,40 @@ func (r *ChannelRouter) Start() error {
}
for _, payment := range payments {
log.Infof("Resuming payment with hash %v", payment.Info.PaymentHash)
log.Infof("Resuming payment %v", payment.Info.PaymentIdentifier)
r.wg.Add(1)
go func(payment *channeldb.InFlightPayment) {
go func(payment *channeldb.MPPayment) {
defer r.wg.Done()
// Get the hashes used for the outstanding HTLCs.
htlcs := make(map[uint64]lntypes.Hash)
for _, a := range payment.HTLCs {
a := a
// We check whether the individual attempts
// have their HTLC hash set, if not we'll fall
// back to the overall payment hash.
hash := payment.Info.PaymentIdentifier
if a.Hash != nil {
hash = *a.Hash
}
htlcs[a.AttemptID] = hash
}
// Since we are not supporting creating more shards
// after a restart (only receiving the result of the
// shards already outstanding), we create a simple
// shard tracker that will map the attempt IDs to
// hashes used for the HTLCs. This will be enough also
// for AMP payments, since we only need the hashes for
// the individual HTLCs to regenerate the circuits, and
// we don't currently persist the root share necessary
// to re-derive them.
shardTracker := shards.NewSimpleShardTracker(
payment.Info.PaymentIdentifier, htlcs,
)
// We create a dummy, empty payment session such that
// we won't make another payment attempt when the
// result for the in-flight attempt is received.
@ -618,16 +646,17 @@ func (r *ChannelRouter) Start() error {
// be tried.
_, _, err := r.sendPayment(
payment.Info.Value, 0,
payment.Info.PaymentHash, 0, paySession,
payment.Info.PaymentIdentifier, 0, paySession,
shardTracker,
)
if err != nil {
log.Errorf("Resuming payment with hash %v "+
"failed: %v.", payment.Info.PaymentHash, err)
log.Errorf("Resuming payment %v failed: %v.",
payment.Info.PaymentIdentifier, err)
return
}
log.Infof("Resumed payment with hash %v completed.",
payment.Info.PaymentHash)
log.Infof("Resumed payment %v completed.",
payment.Info.PaymentIdentifier)
}(payment)
}
@ -1692,9 +1721,13 @@ type LightningPayment struct {
// complete this payment.
CltvLimit uint32
// PaymentHash is the r-hash value to use within the HTLC extended to
// the first hop.
PaymentHash [32]byte
// paymentHash is the r-hash value to use within the HTLC extended to
// the first hop. This won't be set for AMP payments.
paymentHash *lntypes.Hash
// amp is an optional field that is set if and only if this is am AMP
// payment.
amp *AMPOptions
// FinalCLTVDelta is the CTLV expiry delta to use for the _final_ hop
// in the route. This means that the final hop will have a CLTV delta
@ -1763,6 +1796,46 @@ type LightningPayment struct {
MaxShardAmt *lnwire.MilliSatoshi
}
// AMPOptions houses information that must be known in order to send an AMP
// payment.
type AMPOptions struct {
SetID [32]byte
RootShare [32]byte
}
// SetPaymentHash sets the given hash as the payment's overall hash. This
// should only be used for non-AMP payments.
func (l *LightningPayment) SetPaymentHash(hash lntypes.Hash) error {
if l.amp != nil {
return fmt.Errorf("cannot set payment hash for AMP payment")
}
l.paymentHash = &hash
return nil
}
// SetAMP sets the given AMP options for the payment.
func (l *LightningPayment) SetAMP(amp *AMPOptions) error {
if l.paymentHash != nil {
return fmt.Errorf("cannot set amp options for payment " +
"with payment hash")
}
l.amp = amp
return nil
}
// Identifier returns a 32-byte slice that uniquely identifies this single
// payment. For non-AMP payments this will be the payment hash, for AMP
// payments this will be the used SetID.
func (l *LightningPayment) Identifier() [32]byte {
if l.amp != nil {
return l.amp.SetID
}
return *l.paymentHash
}
// SendPayment attempts to send a payment as described within the passed
// LightningPayment. This function is blocking and will return either: when the
// payment is successful, or all candidates routes have been attempted and
@ -1773,7 +1846,7 @@ type LightningPayment struct {
func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte,
*route.Route, error) {
paySession, err := r.preparePayment(payment)
paySession, shardTracker, err := r.preparePayment(payment)
if err != nil {
return [32]byte{}, nil, err
}
@ -1784,15 +1857,15 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte,
// Since this is the first time this payment is being made, we pass nil
// for the existing attempt.
return r.sendPayment(
payment.Amount, payment.FeeLimit, payment.PaymentHash,
payment.PayAttemptTimeout, paySession,
payment.Amount, payment.FeeLimit, payment.Identifier(),
payment.PayAttemptTimeout, paySession, shardTracker,
)
}
// SendPaymentAsync is the non-blocking version of SendPayment. The payment
// result needs to be retrieved via the control tower.
func (r *ChannelRouter) SendPaymentAsync(payment *LightningPayment) error {
paySession, err := r.preparePayment(payment)
paySession, shardTracker, err := r.preparePayment(payment)
if err != nil {
return err
}
@ -1807,12 +1880,12 @@ func (r *ChannelRouter) SendPaymentAsync(payment *LightningPayment) error {
spewPayment(payment))
_, _, err := r.sendPayment(
payment.Amount, payment.FeeLimit, payment.PaymentHash,
payment.PayAttemptTimeout, paySession,
payment.Amount, payment.FeeLimit, payment.Identifier(),
payment.PayAttemptTimeout, paySession, shardTracker,
)
if err != nil {
log.Errorf("Payment with hash %x failed: %v",
payment.PaymentHash, err)
log.Errorf("Payment %x failed: %v",
payment.Identifier(), err)
}
}()
@ -1844,14 +1917,14 @@ func spewPayment(payment *LightningPayment) logClosure {
// preparePayment creates the payment session and registers the payment with the
// control tower.
func (r *ChannelRouter) preparePayment(payment *LightningPayment) (
PaymentSession, error) {
PaymentSession, shards.ShardTracker, error) {
// Before starting the HTLC routing attempt, we'll create a fresh
// payment session which will report our errors back to mission
// control.
paySession, err := r.cfg.SessionSource.NewPaymentSession(payment)
if err != nil {
return nil, err
return nil, nil, err
}
// Record this payment hash with the ControlTower, ensuring it is not
@ -1859,18 +1932,38 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) (
//
// TODO(roasbeef): store records as part of creation info?
info := &channeldb.PaymentCreationInfo{
PaymentHash: payment.PaymentHash,
Value: payment.Amount,
CreationTime: r.cfg.Clock.Now(),
PaymentRequest: payment.PaymentRequest,
PaymentIdentifier: payment.Identifier(),
Value: payment.Amount,
CreationTime: r.cfg.Clock.Now(),
PaymentRequest: payment.PaymentRequest,
}
// Create a new ShardTracker that we'll use during the life cycle of
// this payment.
var shardTracker shards.ShardTracker
switch {
// If this is an AMP payment, we'll use the AMP shard tracker.
case payment.amp != nil:
shardTracker = amp.NewShardTracker(
payment.amp.RootShare, payment.amp.SetID,
*payment.PaymentAddr, payment.Amount,
)
// Otherwise we'll use the simple tracker that will map each attempt to
// the same payment hash.
default:
shardTracker = shards.NewSimpleShardTracker(
payment.Identifier(), nil,
)
}
err = r.cfg.Control.InitPayment(payment.PaymentHash, info)
err = r.cfg.Control.InitPayment(payment.Identifier(), info)
if err != nil {
return nil, err
return nil, nil, err
}
return paySession, nil
return paySession, shardTracker, nil
}
// SendToRoute attempts to send a payment with the given hash through the
@ -1878,7 +1971,7 @@ func (r *ChannelRouter) preparePayment(payment *LightningPayment) (
// information as it is stored in the database. For a successful htlc, this
// information will contain the preimage. If an error occurs after the attempt
// was initiated, both return values will be non-nil.
func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
func (r *ChannelRouter) SendToRoute(htlcHash lntypes.Hash, rt *route.Route) (
*channeldb.HTLCAttempt, error) {
// Calculate amount paid to receiver.
@ -1892,16 +1985,27 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
amt = mpp.TotalMsat()
}
// For non-AMP payments the overall payment identifier will be the same
// hash as used for this HTLC.
paymentIdentifier := htlcHash
// For AMP-payments, we'll use the setID as the unique ID for the
// overall payment.
amp := finalHop.AMP
if amp != nil {
paymentIdentifier = amp.SetID()
}
// Record this payment hash with the ControlTower, ensuring it is not
// already in-flight.
info := &channeldb.PaymentCreationInfo{
PaymentHash: hash,
Value: amt,
CreationTime: r.cfg.Clock.Now(),
PaymentRequest: nil,
PaymentIdentifier: paymentIdentifier,
Value: amt,
CreationTime: r.cfg.Clock.Now(),
PaymentRequest: nil,
}
err := r.cfg.Control.InitPayment(hash, info)
err := r.cfg.Control.InitPayment(paymentIdentifier, info)
switch {
// If this is an MPP attempt and the hash is already registered with
// the database, we can go on to launch the shard.
@ -1912,20 +2016,28 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
return nil, err
}
log.Tracef("Dispatching SendToRoute for hash %v: %v",
hash, newLogClosure(func() string {
log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v",
htlcHash, newLogClosure(func() string {
return spew.Sdump(rt)
}),
)
// Since the HTLC hashes and preimages are specified manually over the
// RPC for SendToRoute requests, we don't have to worry about creating
// a ShardTracker that can generate hashes for AMP payments. Instead we
// create a simple tracker that can just return the hash for the single
// shard we'll now launch.
shardTracker := shards.NewSimpleShardTracker(htlcHash, nil)
// Launch a shard along the given route.
sh := &shardHandler{
router: r,
paymentHash: hash,
router: r,
identifier: paymentIdentifier,
shardTracker: shardTracker,
}
var shardError error
attempt, outcome, err := sh.launchShard(rt)
attempt, outcome, err := sh.launchShard(rt, false)
// With SendToRoute, it can happen that the route exceeds protocol
// constraints. Mark the payment as failed with an internal error.
@ -1933,10 +2045,10 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
err == sphinx.ErrMaxRoutingInfoSizeExceeded {
log.Debugf("Invalid route provided for payment %x: %v",
hash, err)
paymentIdentifier, err)
controlErr := r.cfg.Control.Fail(
hash, channeldb.FailureReasonError,
paymentIdentifier, channeldb.FailureReasonError,
)
if controlErr != nil {
return nil, controlErr
@ -1984,7 +2096,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
reason = &r
}
err = r.cfg.Control.Fail(hash, *reason)
err = r.cfg.Control.Fail(paymentIdentifier, *reason)
if err != nil {
return nil, err
}
@ -2009,9 +2121,9 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, rt *route.Route) (
// router will call this method for every payment still in-flight according to
// the ControlTower.
func (r *ChannelRouter) sendPayment(
totalAmt, feeLimit lnwire.MilliSatoshi, paymentHash lntypes.Hash,
timeout time.Duration,
paySession PaymentSession) ([32]byte, *route.Route, error) {
totalAmt, feeLimit lnwire.MilliSatoshi, identifier lntypes.Hash,
timeout time.Duration, paySession PaymentSession,
shardTracker shards.ShardTracker) ([32]byte, *route.Route, error) {
// We'll also fetch the current block height so we can properly
// calculate the required HTLC time locks within the route.
@ -2026,8 +2138,9 @@ func (r *ChannelRouter) sendPayment(
router: r,
totalAmount: totalAmt,
feeLimit: feeLimit,
paymentHash: paymentHash,
identifier: identifier,
paySession: paySession,
shardTracker: shardTracker,
currentHeight: currentHeight,
}
@ -2088,7 +2201,7 @@ func (r *ChannelRouter) tryApplyChannelUpdate(rt *route.Route,
// error type, this error is either the final outcome of the payment or we need
// to continue with an alternative route. A final outcome is indicated by a
// non-nil return value.
func (r *ChannelRouter) processSendError(paymentID uint64, rt *route.Route,
func (r *ChannelRouter) processSendError(attemptID uint64, rt *route.Route,
sendErr error) *channeldb.FailureReason {
internalErrorReason := channeldb.FailureReasonError
@ -2098,7 +2211,7 @@ func (r *ChannelRouter) processSendError(paymentID uint64, rt *route.Route,
// Report outcome to mission control.
reason, err := r.cfg.MissionControl.ReportPaymentFail(
paymentID, rt, srcIdx, msg,
attemptID, rt, srcIdx, msg,
)
if err != nil {
log.Errorf("Error reporting payment result to mc: %v",

26
routing/router_test.go

@ -275,13 +275,13 @@ func TestSendPaymentRouteFailureFallback(t *testing.T) {
// Craft a LightningPayment struct that'll send a payment from roasbeef
// to luo ji for 1000 satoshis, with a maximum of 1000 satoshis in fees.
var payHash [32]byte
var payHash lntypes.Hash
paymentAmt := lnwire.NewMSatFromSatoshis(1000)
payment := LightningPayment{
Target: ctx.aliases["sophon"],
Amount: paymentAmt,
FeeLimit: noFeeLimit,
PaymentHash: payHash,
paymentHash: &payHash,
}
var preImage [32]byte
@ -510,13 +510,13 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
// Craft a LightningPayment struct that'll send a payment from roasbeef
// to luo ji for 100 satoshis.
var payHash [32]byte
var payHash lntypes.Hash
amt := lnwire.NewMSatFromSatoshis(1000)
payment := LightningPayment{
Target: ctx.aliases["sophon"],
Amount: amt,
FeeLimit: noFeeLimit,
PaymentHash: payHash,
paymentHash: &payHash,
}
var preImage [32]byte
@ -611,13 +611,13 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
// Craft a LightningPayment struct that'll send a payment from roasbeef
// to sophon for 1k satoshis.
var payHash [32]byte
var payHash lntypes.Hash
amt := lnwire.NewMSatFromSatoshis(1000)
payment := LightningPayment{
Target: ctx.aliases["sophon"],
Amount: amt,
FeeLimit: noFeeLimit,
PaymentHash: payHash,
paymentHash: &payHash,
}
var preImage [32]byte
@ -720,7 +720,7 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
// Once again, Roasbeef should route around Goku since they disagree
// w.r.t to the block height, and instead go through Pham Nuwen. We
// flip a bit in the payment hash to allow resending this payment.
payment.PaymentHash[1] ^= 1
payment.paymentHash[1] ^= 1
paymentPreImage, rt, err = ctx.router.SendPayment(&payment)
if err != nil {
t.Fatalf("unable to send payment: %v", err)
@ -744,13 +744,13 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
// Craft a LightningPayment struct that'll send a payment from roasbeef
// to luo ji for 1000 satoshis, with a maximum of 1000 satoshis in fees.
var payHash [32]byte
var payHash lntypes.Hash
paymentAmt := lnwire.NewMSatFromSatoshis(1000)
payment := LightningPayment{
Target: ctx.aliases["sophon"],
Amount: paymentAmt,
FeeLimit: noFeeLimit,
PaymentHash: payHash,
paymentHash: &payHash,
}
var preImage [32]byte
@ -887,7 +887,7 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
})
// We flip a bit in the payment hash to allow resending this payment.
payment.PaymentHash[1] ^= 1
payment.paymentHash[1] ^= 1
paymentPreImage, rt, err = ctx.router.SendPayment(&payment)
if err != nil {
t.Fatalf("unable to send payment: %v", err)
@ -2565,11 +2565,12 @@ func TestUnknownErrorSource(t *testing.T) {
}
// Create a payment to node c.
var payHash lntypes.Hash
payment := LightningPayment{
Target: ctx.aliases["c"],
Amount: lnwire.NewMSatFromSatoshis(1000),
FeeLimit: noFeeLimit,
PaymentHash: lntypes.Hash{},
paymentHash: &payHash,
}
// We'll modify the SendToSwitch method so that it simulates hop b as a
@ -2616,7 +2617,8 @@ func TestUnknownErrorSource(t *testing.T) {
// Send off the payment request to the router. We expect the payment to
// fail because both routes have been pruned.
payment.PaymentHash = lntypes.Hash{1}
payHash = lntypes.Hash{1}
payment.paymentHash = &payHash
_, _, err = ctx.router.SendPayment(&payment)
if err == nil {
t.Fatalf("expected payment to fail")

135
routing/shards/shard_tracker.go

@ -0,0 +1,135 @@
package shards
import (
"fmt"
"sync"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/record"
)
// PaymentShard is an interface representing a shard tracked by the
// ShardTracker. It contains options that are specific to the given shard that
// might differ from the overall payment.
type PaymentShard interface {
// Hash returns the hash used for the HTLC representing this shard.
Hash() lntypes.Hash
// MPP returns any extra MPP records that should be set for the final
// hop on the route used by this shard.
MPP() *record.MPP
// AMP returns any extra AMP records that should be set for the final
// hop on the route used by this shard.
AMP() *record.AMP
}
// ShardTracker is an interfae representing a tracker that keeps track of the
// inflight shards of a payment, and is able to assign new shards the correct
// options such as hash and extra records.
type ShardTracker interface {
// NewShard registers a new attempt with the ShardTracker and returns a
// new shard representing this attempt. This attempt's shard should be
// canceled if it ends up not being used by the overall payment, i.e.
// if the attempt fails.
NewShard(uint64, bool) (PaymentShard, error)
// CancelShard cancel's the shard corresponding to the given attempt
// ID. This lets the ShardTracker free up any slots used by this shard,
// and in case of AMP payments return the share used by this shard to
// the root share.
CancelShard(uint64) error
// GetHash retrieves the hash used by the shard of the given attempt
// ID. This wil return an error if the attempt ID is unknown.
GetHash(uint64) (lntypes.Hash, error)
}
// Shard is a struct used for simple shards where we obly need to keep map it
// to a single hash.
type Shard struct {
hash lntypes.Hash
}
// Hash returns the hash used for the HTLC representing this shard.
func (s *Shard) Hash() lntypes.Hash {
return s.hash
}
// MPP returns any extra MPP records that should be set for the final hop on
// the route used by this shard.
func (s *Shard) MPP() *record.MPP {
return nil
}
// AMP returns any extra AMP records that should be set for the final hop on
// the route used by this shard.
func (s *Shard) AMP() *record.AMP {
return nil
}
// SimpleShardTracker is an implementation of the ShardTracker interface that
// simply maps attempt IDs to hashes. New shards will be given a static payment
// hash. This should be used for regular and MPP payments, in addition to
// resumed payments where all the attempt's hashes have already been created.
type SimpleShardTracker struct {
hash lntypes.Hash
shards map[uint64]lntypes.Hash
sync.Mutex
}
// A compile time check to ensure SimpleShardTracker implements the
// ShardTracker interface.
var _ ShardTracker = (*SimpleShardTracker)(nil)
// NewSimpleShardTracker creates a new intance of the SimpleShardTracker with
// the given payment hash and existing attempts.
func NewSimpleShardTracker(paymentHash lntypes.Hash,
shards map[uint64]lntypes.Hash) ShardTracker {
if shards == nil {
shards = make(map[uint64]lntypes.Hash)
}
return &SimpleShardTracker{
hash: paymentHash,
shards: shards,
}
}
// NewShard registers a new attempt with the ShardTracker and returns a
// new shard representing this attempt. This attempt's shard should be canceled
// if it ends up not being used by the overall payment, i.e. if the attempt
// fails.
func (m *SimpleShardTracker) NewShard(id uint64, _ bool) (PaymentShard, error) {
m.Lock()
m.shards[id] = m.hash
m.Unlock()
return &Shard{
hash: m.hash,
}, nil
}
// CancelShard cancel's the shard corresponding to the given attempt ID.
func (m *SimpleShardTracker) CancelShard(id uint64) error {
m.Lock()
delete(m.shards, id)
m.Unlock()
return nil
}
// GetHash retrieves the hash used by the shard of the given attempt ID. This
// will return an error if the attempt ID is unknown.
func (m *SimpleShardTracker) GetHash(id uint64) (lntypes.Hash, error) {
m.Lock()
hash, ok := m.shards[id]
m.Unlock()
if !ok {
return lntypes.Hash{}, fmt.Errorf("hash for attempt id %v "+
"not found", id)
}
return hash, nil
}

47
routing/shards/shard_tracker_test.go

@ -0,0 +1,47 @@
package shards_test
import (
"crypto/rand"
"testing"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing/shards"
"github.com/stretchr/testify/require"
)
// TestSimpleShardTracker tests that the simple tracker that keeps a map from
// attemptID-> payment hash works.
func TestSimpleShardTracker(t *testing.T) {
var testHashes [2]lntypes.Hash
for i := range testHashes {
_, err := rand.Read(testHashes[i][:])
require.NoError(t, err)
}
startAttempts := map[uint64]lntypes.Hash{
1: testHashes[1],
}
tracker := shards.NewSimpleShardTracker(testHashes[0], startAttempts)
// Trying to retrieve a hash for id 0 should result in an error.
_, err := tracker.GetHash(0)
require.Error(t, err)
// Getting id 1 should workd.
hash1, err := tracker.GetHash(1)
require.NoError(t, err)
require.Equal(t, testHashes[1], hash1)
// Finally, create a new shard and immediately retrieve the hash.
shard, err := tracker.NewShard(2, false)
require.NoError(t, err)
// It's hash should be the tracker's overall payment hash.
hash2, err := tracker.GetHash(2)
require.NoError(t, err)
require.Equal(t, testHashes[0], shard.Hash())
require.Equal(t, testHashes[0], hash2)
}

5
rpcserver.go

@ -4419,7 +4419,6 @@ func (r *rpcServer) dispatchPaymentIntent(
FinalCLTVDelta: payIntent.cltvDelta,
FeeLimit: payIntent.feeLimit,
CltvLimit: payIntent.cltvLimit,
PaymentHash: payIntent.rHash,
RouteHints: payIntent.routeHints,
OutgoingChannelIDs: payIntent.outgoingChannelIDs,
LastHop: payIntent.lastHop,
@ -4433,6 +4432,10 @@ func (r *rpcServer) dispatchPaymentIntent(
// Users need to use routerrpc for that.
MaxParts: 1,
}
err := payment.SetPaymentHash(payIntent.rHash)
if err != nil {
return nil, err
}
preImage, route, routerErr = r.server.chanRouter.SendPayment(
payment,

Loading…
Cancel
Save