From 8fe4de88c1b8d12b02fd10553f82d15ddc431703 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:47:01 -0700 Subject: [PATCH 01/22] record: convert child_index from uint16 to uint32 --- record/amp.go | 14 +++++++------- record/record_test.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/record/amp.go b/record/amp.go index 72b4cbf4272..970648053dd 100644 --- a/record/amp.go +++ b/record/amp.go @@ -16,12 +16,12 @@ const AMPOnionType tlv.Type = 10 type AMP struct { rootShare [32]byte setID [32]byte - childIndex uint16 + childIndex uint32 } // NewAMP generate a new AMP record with the given root_share, set_id, and // child_index. -func NewAMP(rootShare, setID [32]byte, childIndex uint16) *AMP { +func NewAMP(rootShare, setID [32]byte, childIndex uint32) *AMP { return &{ rootShare: rootShare, setID: setID, @@ -40,7 +40,7 @@ func (a *AMP) SetID() [32]byte { } // ChildIndex returns the child index contained in the AMP record. -func (a *AMP) ChildIndex() uint16 { +func (a *AMP) ChildIndex() uint32 { return a.childIndex } @@ -55,7 +55,7 @@ func AMPEncoder(w io.Writer, val interface{}, buf *[8]byte) error { return err } - return tlv.ETUint16T(w, v.childIndex, buf) + return tlv.ETUint32T(w, v.childIndex, buf) } return tlv.NewTypeForEncodingErr(val, "AMP") } @@ -69,7 +69,7 @@ const ( // maxAMPLength is the maximum legnth of a serialized AMP TLV record, // which occurs when the truncated endoing of a child_index takes 2 // bytes. - maxAMPLength = 66 + maxAMPLength = 68 ) // AMPDecoder reads the AMP record from the provided io.Reader. @@ -83,7 +83,7 @@ func AMPDecoder(r io.Reader, val interface{}, buf *[8]byte, l uint64) error { return err } - return tlv.DTUint16(r, &v.childIndex, buf, l-64) + return tlv.DTUint32(r, &v.childIndex, buf, l-minAMPLength) } return tlv.NewTypeForDecodingErr(val, "AMP", l, maxAMPLength) } @@ -97,7 +97,7 @@ func (a *AMP) Record() tlv.Record { // PayloadSize returns the size this record takes up in encoded form. func (a *AMP) PayloadSize() uint64 { - return 32 + 32 + tlv.SizeTUint16(a.childIndex) + return 32 + 32 + tlv.SizeTUint32(a.childIndex) } // String returns a human-readble description of the amp payload fields. diff --git a/record/record_test.go b/record/record_test.go index 8c39790ed84..45faa9f73d7 100644 --- a/record/record_test.go +++ b/record/record_test.go @@ -21,7 +21,7 @@ var ( testAddr = [32]byte{0x01, 0x02} testShare = [32]byte{0x03, 0x04} testSetID = [32]byte{0x05, 0x06} - testChildIndex = uint16(17) + testChildIndex = uint32(17) ) var recordEncDecTests = []recordEncDecTest{ From 82b4f11292476437254223e180a1a9bf31fe08c9 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:47:18 -0700 Subject: [PATCH 02/22] record/amp: use switch from 10 -> 14 for AMP TLV type This is to not conflict with trampoline BOLT. --- record/amp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/record/amp.go b/record/amp.go index 970648053dd..53c9b44191c 100644 --- a/record/amp.go +++ b/record/amp.go @@ -9,7 +9,7 @@ import ( // AMPOnionType is the type used in the onion to reference the AMP fields: // root_share, set_id, and child_index. -const AMPOnionType tlv.Type = 10 +const AMPOnionType tlv.Type = 14 // AMP is a record that encodes the fields necessary for atomic multi-path // payments. From 135a0a9f7ffb43635df2de9f05bbc57daa8acfa9 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:47:33 -0700 Subject: [PATCH 03/22] htlcswitch/hop: make unknown required type const Currently we use the AMP record type, this allows us to change it easily as we add new known records. We also bump this to 0x0c instead of 0x0a. --- htlcswitch/hop/payload_test.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/htlcswitch/hop/payload_test.go b/htlcswitch/hop/payload_test.go index b0a92534f4b..bfe2c134e8e 100644 --- a/htlcswitch/hop/payload_test.go +++ b/htlcswitch/hop/payload_test.go @@ -10,6 +10,8 @@ import ( "github.com/lightningnetwork/lnd/record" ) +const testUnknownRequiredType = 0x10 + type decodePayloadTest struct { name string payload []byte @@ -81,21 +83,26 @@ var decodePayloadTests = []decodePayloadTest{ }, }, { - name: "required type after omitted hop id", - payload: []byte{0x02, 0x00, 0x04, 0x00, 0x0a, 0x00}, + name: "required type after omitted hop id", + payload: []byte{ + 0x02, 0x00, 0x04, 0x00, + testUnknownRequiredType, 0x00, + }, expErr: hop.ErrInvalidPayload{ - Type: 10, + Type: testUnknownRequiredType, Violation: hop.RequiredViolation, FinalHop: true, }, }, { name: "required type after included hop id", - payload: []byte{0x02, 0x00, 0x04, 0x00, 0x06, 0x08, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + payload: []byte{ + 0x02, 0x00, 0x04, 0x00, 0x06, 0x08, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + testUnknownRequiredType, 0x00, }, expErr: hop.ErrInvalidPayload{ - Type: 10, + Type: testUnknownRequiredType, Violation: hop.RequiredViolation, FinalHop: false, }, From c2729cbbbd49118abd6cce428f682dac09c45eda Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:47:58 -0700 Subject: [PATCH 04/22] htlcswitch/hop: parse and validate AMP records --- htlcswitch/hop/payload.go | 18 ++++++++ htlcswitch/hop/payload_test.go | 82 ++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/htlcswitch/hop/payload.go b/htlcswitch/hop/payload.go index c6a25ba6a26..e233537f410 100644 --- a/htlcswitch/hop/payload.go +++ b/htlcswitch/hop/payload.go @@ -119,6 +119,7 @@ func NewPayloadFromReader(r io.Reader) (*Payload, error) { amt uint64 cltv uint32 mpp = &record.MPP{} + amp = &record.AMP{} ) tlvStream, err := tlv.NewStream( @@ -126,6 +127,7 @@ func NewPayloadFromReader(r io.Reader) (*Payload, error) { record.NewLockTimeRecord(&cltv), record.NewNextHopIDRecord(&cid), mpp.Record(), + amp.Record(), ) if err != nil { return nil, err @@ -160,6 +162,12 @@ func NewPayloadFromReader(r io.Reader) (*Payload, error) { mpp = nil } + // If no AMP field was parsed, set the MPP field on the resulting + // payload to nil. + if _, ok := parsedTypes[record.AMPOnionType]; !ok { + amp = nil + } + // Filter out the custom records. customRecords := NewCustomRecords(parsedTypes) @@ -171,6 +179,7 @@ func NewPayloadFromReader(r io.Reader) (*Payload, error) { OutgoingCTLV: cltv, }, MPP: mpp, + AMP: amp, customRecords: customRecords, }, nil } @@ -207,6 +216,7 @@ func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap, _, hasLockTime := parsedTypes[record.LockTimeOnionType] _, hasNextHop := parsedTypes[record.NextHopOnionType] _, hasMPP := parsedTypes[record.MPPOnionType] + _, hasAMP := parsedTypes[record.AMPOnionType] switch { @@ -243,6 +253,14 @@ func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap, Violation: IncludedViolation, FinalHop: isFinalHop, } + + // Intermediate nodes should never receive AMP fields. + case !isFinalHop && hasAMP: + return ErrInvalidPayload{ + Type: record.AMPOnionType, + Violation: IncludedViolation, + FinalHop: isFinalHop, + } } return nil diff --git a/htlcswitch/hop/payload_test.go b/htlcswitch/hop/payload_test.go index bfe2c134e8e..c7abc9fad14 100644 --- a/htlcswitch/hop/payload_test.go +++ b/htlcswitch/hop/payload_test.go @@ -8,6 +8,7 @@ import ( "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" + "github.com/stretchr/testify/require" ) const testUnknownRequiredType = 0x10 @@ -18,6 +19,7 @@ type decodePayloadTest struct { expErr error expCustomRecords map[uint64][]byte shouldHaveMPP bool + shouldHaveAMP bool } var decodePayloadTests = []decodePayloadTest{ @@ -183,6 +185,37 @@ var decodePayloadTests = []decodePayloadTest{ FinalHop: false, }, }, + { + name: "intermediate hop with amp", + payload: []byte{ + // amount + 0x02, 0x00, + // cltv + 0x04, 0x00, + // next hop id + 0x06, 0x08, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // amp + 0x0e, 0x41, + // amp.root_share + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + // amp.set_id + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + // amp.child_index + 0x09, + }, + expErr: hop.ErrInvalidPayload{ + Type: record.AMPOnionType, + Violation: hop.IncludedViolation, + FinalHop: false, + }, + }, { name: "final hop with mpp", payload: []byte{ @@ -201,6 +234,30 @@ var decodePayloadTests = []decodePayloadTest{ expErr: nil, shouldHaveMPP: true, }, + { + name: "final hop with amp", + payload: []byte{ + // amount + 0x02, 0x00, + // cltv + 0x04, 0x00, + // amp + 0x0e, 0x41, + // amp.root_share + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + // amp.set_id + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + // amp.child_index + 0x09, + }, + shouldHaveAMP: true, + }, } // TestDecodeHopPayloadRecordValidation asserts that parsing the payloads in the @@ -223,6 +280,20 @@ func testDecodeHopPayloadValidation(t *testing.T, test decodePayloadTest) { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, } + + testRootShare = [32]byte{ + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + } + testSetID = [32]byte{ + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + } + testChildIndex = uint32(9) ) p, err := hop.NewPayloadFromReader(bytes.NewReader(test.payload)) @@ -249,6 +320,17 @@ func testDecodeHopPayloadValidation(t *testing.T, test decodePayloadTest) { t.Fatalf("unexpected MPP payload") } + if test.shouldHaveAMP { + if p.AMP == nil { + t.Fatalf("payload should have AMP record") + } + require.Equal(t, testRootShare, p.AMP.RootShare()) + require.Equal(t, testSetID, p.AMP.SetID()) + require.Equal(t, testChildIndex, p.AMP.ChildIndex()) + } else if p.AMP != nil { + t.Fatalf("unexpected AMP payload") + } + // Convert expected nil map to empty map, because we always expect an // initiated map from the payload. expCustomRecords := make(record.CustomSet) From 438b03afa42c6a9fd19f7cb123b4babda2367caa Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:48:08 -0700 Subject: [PATCH 05/22] features: define temporary AMP feature bits 30/31 --- feature/default_sets.go | 5 +++++ feature/deps.go | 3 +++ feature/manager.go | 2 ++ lnwire/features.go | 12 ++++++++++++ 4 files changed, 22 insertions(+) diff --git a/feature/default_sets.go b/feature/default_sets.go index 50b503f8ca1..4c0de5690cf 100644 --- a/feature/default_sets.go +++ b/feature/default_sets.go @@ -51,4 +51,9 @@ var defaultSetDesc = setDesc{ SetInit: {}, // I SetNodeAnn: {}, // N }, + lnwire.AMPOptional: { + SetInit: {}, // I + SetNodeAnn: {}, // N + SetInvoice: {}, // 9 + }, } diff --git a/feature/deps.go b/feature/deps.go index c2b8f175698..51ee37e9bfc 100644 --- a/feature/deps.go +++ b/feature/deps.go @@ -58,6 +58,9 @@ var deps = depDesc{ lnwire.AnchorsOptional: { lnwire.StaticRemoteKeyOptional: {}, }, + lnwire.AMPOptional: { + lnwire.PaymentAddrOptional: {}, + }, } // ValidateDeps asserts that a feature vector sets all features and their diff --git a/feature/manager.go b/feature/manager.go index cbaf8f57f10..9891807151e 100644 --- a/feature/manager.go +++ b/feature/manager.go @@ -77,6 +77,8 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) { raw.Unset(lnwire.PaymentAddrRequired) raw.Unset(lnwire.MPPOptional) raw.Unset(lnwire.MPPRequired) + raw.Unset(lnwire.AMPOptional) + raw.Unset(lnwire.AMPRequired) } if cfg.NoStaticRemoteKey { raw.Unset(lnwire.StaticRemoteKeyOptional) diff --git a/lnwire/features.go b/lnwire/features.go index 279e72c9e42..9dfa07ee1e3 100644 --- a/lnwire/features.go +++ b/lnwire/features.go @@ -129,6 +129,16 @@ const ( // transactions, which also imply anchor commitments. AnchorsZeroFeeHtlcTxOptional FeatureBit = 23 + // AMPRequired is a required feature bit that signals that the receiver + // of a payment supports accepts spontaneous payments, i.e. + // sender-generated preimages according to BOLT XX. + AMPRequired FeatureBit = 30 + + // AMPOptional is an optional feature bit that signals that the receiver + // of a payment supports accepts spontaneous payments, i.e. + // sender-generated preimages according to BOLT XX. + AMPOptional FeatureBit = 31 + // maxAllowedSize is a maximum allowed size of feature vector. // // NOTE: Within the protocol, the maximum allowed message size is 65535 @@ -172,6 +182,8 @@ var Features = map[FeatureBit]string{ AnchorsZeroFeeHtlcTxOptional: "anchors-zero-fee-htlc-tx", WumboChannelsRequired: "wumbo-channels", WumboChannelsOptional: "wumbo-channels", + AMPRequired: "amp", + AMPOptional: "amp", } // RawFeatureVector represents a set of feature bits as defined in BOLT-09. A From be6698447e546d1a19be1721ea0da0b9591b4ae1 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:48:23 -0700 Subject: [PATCH 06/22] channeldb/invoice: add InvoiceRefByAddr --- channeldb/invoice_test.go | 7 +++++++ channeldb/invoices.go | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index 3b0416d1c82..7132ba27ae1 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -1225,6 +1225,13 @@ func TestInvoiceRef(t *testing.T) { require.Equal(t, lntypes.Hash{}, refBySetID.PayHash()) require.Equal(t, (*[32]byte)(nil), refBySetID.PayAddr()) require.Equal(t, &setID, refBySetID.SetID()) + + // An InvoiceRef by pay addr should only return a pay addr, but nil for + // pay hash and set id. + refByAddr := InvoiceRefByAddr(payAddr) + require.Equal(t, (*lntypes.Hash)(nil), refByAddr.PayHash()) + require.Equal(t, &payAddr, refByAddr.PayAddr()) + require.Equal(t, (*[32]byte)(nil), refByAddr.SetID()) } // TestHTLCSet asserts that HTLCSet returns the proper set of accepted HTLCs diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 7598575aa42..444602aeab9 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -236,6 +236,14 @@ func InvoiceRefByHashAndAddr(payHash lntypes.Hash, } } +// InvoiceRefByAddr creates an InvoiceRef that queries the payment addr index +// for an invoice with the provided payment address. +func InvoiceRefByAddr(addr [32]byte) InvoiceRef { + return InvoiceRef{ + payAddr: &addr, + } +} + // InvoiceRefBySetID creates an InvoiceRef that queries the set id index for an // invoice with the provided setID. If the invoice is not found, the query will // not fallback to payHash or payAddr. @@ -903,6 +911,10 @@ func fetchInvoiceNumByRef(invoiceIndex, payAddrIndex, setIDIndex kvdb.RBucket, return invoiceNumByAddr, nil + // Return invoices by payment addr only. + case invoiceNumByAddr != nil: + return invoiceNumByAddr, nil + // If we were only able to reference the invoice by hash, return the // corresponding invoice number. This can happen when no payment address // was provided, or if it didn't match anything in our records. From 174d5775243ff95153b6cdd985ee5d5fdcc22411 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:48:32 -0700 Subject: [PATCH 07/22] channeldb: make payhash on InvoiceRef optional Currently we support queries by payHash or payHash+payAddr. For handling of AMP HTLCs, we only need to support querying by payAddr. --- channeldb/invoice_test.go | 38 +++++++++++++++++-- channeldb/invoices.go | 64 ++++++++++++++++++++++---------- invoices/invoiceregistry.go | 10 ++++- invoices/invoiceregistry_test.go | 16 +++----- 4 files changed, 93 insertions(+), 35 deletions(-) diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index 7132ba27ae1..af1d967b078 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -1208,21 +1208,21 @@ func TestInvoiceRef(t *testing.T) { // An InvoiceRef by hash should return the provided hash and a nil // payment addr. refByHash := InvoiceRefByHash(payHash) - require.Equal(t, payHash, refByHash.PayHash()) + require.Equal(t, &payHash, refByHash.PayHash()) require.Equal(t, (*[32]byte)(nil), refByHash.PayAddr()) require.Equal(t, (*[32]byte)(nil), refByHash.SetID()) // An InvoiceRef by hash and addr should return the payment hash and // payment addr passed to the constructor. refByHashAndAddr := InvoiceRefByHashAndAddr(payHash, payAddr) - require.Equal(t, payHash, refByHashAndAddr.PayHash()) + require.Equal(t, &payHash, refByHashAndAddr.PayHash()) require.Equal(t, &payAddr, refByHashAndAddr.PayAddr()) require.Equal(t, (*[32]byte)(nil), refByHashAndAddr.SetID()) // An InvoiceRef by set id should return an empty pay hash, a nil pay // addr, and a reference to the given set id. refBySetID := InvoiceRefBySetID(setID) - require.Equal(t, lntypes.Hash{}, refBySetID.PayHash()) + require.Equal(t, (*lntypes.Hash)(nil), refBySetID.PayHash()) require.Equal(t, (*[32]byte)(nil), refBySetID.PayAddr()) require.Equal(t, &setID, refBySetID.SetID()) @@ -1533,6 +1533,38 @@ func getUpdateInvoiceAMPSettle(setID *[32]byte) InvoiceUpdateCallback { } } +// TestUnexpectedInvoicePreimage asserts that legacy or MPP invoices cannot be +// settled when referenced by payment address only. Since regular or MPP +// payments do not store the payment hash explicitly (it is stored in the +// index), this enforces that they can only be updated using a InvoiceRefByHash +// or InvoiceRefByHashOrAddr. +func TestUnexpectedInvoicePreimage(t *testing.T) { + t.Parallel() + + db, cleanup, err := MakeTestDB() + defer cleanup() + require.NoError(t, err, "unable to make test db") + + invoice, err := randInvoice(lnwire.MilliSatoshi(100)) + require.NoError(t, err) + + // Add a random invoice indexed by payment hash and payment addr. + paymentHash := invoice.Terms.PaymentPreimage.Hash() + _, err = db.AddInvoice(invoice, paymentHash) + require.NoError(t, err) + + // Attempt to update the invoice by pay addr only. This will fail since, + // in order to settle an MPP invoice, the InvoiceRef must present a + // payment hash against which to validate the preimage. + _, err = db.UpdateInvoice( + InvoiceRefByAddr(invoice.Terms.PaymentAddr), + getUpdateInvoice(invoice.Terms.Value), + ) + + //Assert that we get ErrUnexpectedInvoicePreimage. + require.Error(t, ErrUnexpectedInvoicePreimage, err) +} + // TestDeleteInvoices tests that deleting a list of invoices will succeed // if all delete references are valid, or will fail otherwise. func TestDeleteInvoices(t *testing.T) { diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 444602aeab9..613960bfe3f 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -122,6 +122,13 @@ var ( // ErrEmptyHTLCSet is returned when attempting to accept or settle and // HTLC set that has no HTLCs. ErrEmptyHTLCSet = errors.New("cannot settle/accept empty HTLC set") + + // ErrUnexpectedInvoicePreimage is returned when an invoice-level + // preimage is provided when trying to settle an invoice that shouldn't + // have one, e.g. an AMP invoice. + ErrUnexpectedInvoicePreimage = errors.New( + "unexpected invoice preimage provided on settle", + ) ) // ErrDuplicateSetID is an error returned when attempting to adding an AMP HTLC @@ -198,7 +205,7 @@ type InvoiceRef struct { // payHash is the payment hash of the target invoice. All invoices are // currently indexed by payment hash. This value will be used as a // fallback when no payment address is known. - payHash lntypes.Hash + payHash *lntypes.Hash // payAddr is the payment addr of the target invoice. Newer invoices // (0.11 and up) are indexed by payment address in addition to payment @@ -220,7 +227,7 @@ type InvoiceRef struct { // its payment hash. func InvoiceRefByHash(payHash lntypes.Hash) InvoiceRef { return InvoiceRef{ - payHash: payHash, + payHash: &payHash, } } @@ -231,7 +238,7 @@ func InvoiceRefByHashAndAddr(payHash lntypes.Hash, payAddr [32]byte) InvoiceRef { return InvoiceRef{ - payHash: payHash, + payHash: &payHash, payAddr: &payAddr, } } @@ -253,9 +260,15 @@ func InvoiceRefBySetID(setID [32]byte) InvoiceRef { } } -// PayHash returns the target invoice's payment hash. -func (r InvoiceRef) PayHash() lntypes.Hash { - return r.payHash +// PayHash returns the optional payment hash of the target invoice. +// +// NOTE: This value may be nil. +func (r InvoiceRef) PayHash() *lntypes.Hash { + if r.payHash != nil { + hash := *r.payHash + return &hash + } + return nil } // PayAddr returns the optional payment address of the target invoice. @@ -887,19 +900,27 @@ func fetchInvoiceNumByRef(invoiceIndex, payAddrIndex, setIDIndex kvdb.RBucket, payHash := ref.PayHash() payAddr := ref.PayAddr() - var ( - invoiceNumByHash = invoiceIndex.Get(payHash[:]) - invoiceNumByAddr []byte - ) - if payAddr != nil { - // Only allow lookups for payment address if it is not a blank - // payment address, which is a special-cased value for legacy - // keysend invoices. - if *payAddr != BlankPayAddr { - invoiceNumByAddr = payAddrIndex.Get(payAddr[:]) + getInvoiceNumByHash := func() []byte { + if payHash != nil { + return invoiceIndex.Get(payHash[:]) } + return nil } + getInvoiceNumByAddr := func() []byte { + if payAddr != nil { + // Only allow lookups for payment address if it is not a + // blank payment address, which is a special-cased value + // for legacy keysend invoices. + if *payAddr != BlankPayAddr { + return payAddrIndex.Get(payAddr[:]) + } + } + return nil + } + + invoiceNumByHash := getInvoiceNumByHash() + invoiceNumByAddr := getInvoiceNumByAddr() switch { // If payment address and payment hash both reference an existing @@ -1745,7 +1766,7 @@ func copyInvoice(src *Invoice) *Invoice { // updateInvoice fetches the invoice, obtains the update descriptor from the // callback and applies the updates in a single db transaction. -func (d *DB) updateInvoice(hash lntypes.Hash, invoices, +func (d *DB) updateInvoice(hash *lntypes.Hash, invoices, settleIndex, setIDIndex kvdb.RwBucket, invoiceNum []byte, callback InvoiceUpdateCallback) (*Invoice, error) { @@ -1913,7 +1934,7 @@ func (d *DB) updateInvoice(hash lntypes.Hash, invoices, } // updateInvoiceState validates and processes an invoice state update. -func updateInvoiceState(invoice *Invoice, hash lntypes.Hash, +func updateInvoiceState(invoice *Invoice, hash *lntypes.Hash, update InvoiceStateUpdateDesc) error { // Returning to open is never allowed from any state. @@ -1962,9 +1983,14 @@ func updateInvoiceState(invoice *Invoice, hash lntypes.Hash, switch { + // If an invoice-level preimage was supplied, but the InvoiceRef + // doesn't specify a hash (e.g. AMP invoices) we fail. + case update.Preimage != nil && hash == nil: + return ErrUnexpectedInvoicePreimage + // Validate the supplied preimage for non-AMP invoices. case update.Preimage != nil: - if update.Preimage.Hash() != hash { + if update.Preimage.Hash() != *hash { return ErrInvoicePreimageMismatch } invoice.Terms.PaymentPreimage = update.Preimage diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index e6e4093bcb5..4f594ee4121 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -377,7 +377,8 @@ func (i *InvoiceRegistry) invoiceEventLoop() { func (i *InvoiceRegistry) dispatchToSingleClients(event *invoiceEvent) { // Dispatch to single invoice subscribers. for _, client := range i.singleNotificationClients { - if client.invoiceRef.PayHash() != event.hash { + payHash := client.invoiceRef.PayHash() + if payHash == nil || *payHash != event.hash { continue } @@ -524,8 +525,13 @@ func (i *InvoiceRegistry) deliverSingleBacklogEvents( return err } + payHash := client.invoiceRef.PayHash() + if payHash == nil { + return nil + } + err = client.notify(&invoiceEvent{ - hash: client.invoiceRef.PayHash(), + hash: *payHash, invoice: &invoice, }) if err != nil { diff --git a/invoices/invoiceregistry_test.go b/invoices/invoiceregistry_test.go index 9e465eaaad4..2056a90173d 100644 --- a/invoices/invoiceregistry_test.go +++ b/invoices/invoiceregistry_test.go @@ -29,9 +29,7 @@ func TestSettleInvoice(t *testing.T) { } defer subscription.Cancel() - if subscription.invoiceRef.PayHash() != testInvoicePaymentHash { - t.Fatalf("expected subscription for provided hash") - } + require.Equal(t, subscription.invoiceRef.PayHash(), &testInvoicePaymentHash) // Add the invoice. addIdx, err := ctx.registry.AddInvoice(testInvoice, testInvoicePaymentHash) @@ -244,9 +242,7 @@ func testCancelInvoice(t *testing.T, gc bool) { } defer subscription.Cancel() - if subscription.invoiceRef.PayHash() != testInvoicePaymentHash { - t.Fatalf("expected subscription for provided hash") - } + require.Equal(t, subscription.invoiceRef.PayHash(), &testInvoicePaymentHash) // Add the invoice. amt := lnwire.MilliSatoshi(100000) @@ -404,9 +400,7 @@ func TestSettleHoldInvoice(t *testing.T) { } defer subscription.Cancel() - if subscription.invoiceRef.PayHash() != testInvoicePaymentHash { - t.Fatalf("expected subscription for provided hash") - } + require.Equal(t, subscription.invoiceRef.PayHash(), &testInvoicePaymentHash) // Add the invoice. _, err = registry.AddInvoice(testHodlInvoice, testInvoicePaymentHash) @@ -1211,7 +1205,7 @@ func TestSettleInvoicePaymentAddrRequired(t *testing.T) { defer subscription.Cancel() require.Equal( - t, subscription.invoiceRef.PayHash(), testInvoicePaymentHash, + t, subscription.invoiceRef.PayHash(), &testInvoicePaymentHash, ) // Add the invoice, which requires the MPP payload to always be @@ -1287,7 +1281,7 @@ func TestSettleInvoicePaymentAddrRequiredOptionalGrace(t *testing.T) { defer subscription.Cancel() require.Equal( - t, subscription.invoiceRef.PayHash(), testInvoicePaymentHash, + t, subscription.invoiceRef.PayHash(), &testInvoicePaymentHash, ) // Add the invoice, which requires the MPP payload to always be From 7bed359296a9207091ad201081761130b6ddea1b Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:48:41 -0700 Subject: [PATCH 08/22] channeldb: refactor InvoiceRef.String() with all optional fields --- channeldb/invoices.go | 12 ++++++++++-- invoices/update.go | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 613960bfe3f..5a607ce95c8 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "strings" "time" "github.com/lightningnetwork/lnd/channeldb/kvdb" @@ -295,10 +296,17 @@ func (r InvoiceRef) SetID() *[32]byte { // String returns a human-readable representation of an InvoiceRef. func (r InvoiceRef) String() string { + var ids []string + if r.payHash != nil { + ids = append(ids, fmt.Sprintf("pay_hash=%v", *r.payHash)) + } if r.payAddr != nil { - return fmt.Sprintf("(pay_hash=%v, pay_addr=%x)", r.payHash, *r.payAddr) + ids = append(ids, fmt.Sprintf("pay_addr=%x", *r.payAddr)) + } + if r.setID != nil { + ids = append(ids, fmt.Sprintf("set_id=%x", *r.setID)) } - return fmt.Sprintf("(pay_hash=%v)", r.payHash) + return fmt.Sprintf("(%s)", strings.Join(ids, ", ")) } // ContractState describes the state the invoice is in. diff --git a/invoices/update.go b/invoices/update.go index 45435ca854e..c656914328c 100644 --- a/invoices/update.go +++ b/invoices/update.go @@ -47,7 +47,7 @@ func (i invoiceUpdateCtx) setID() *[32]byte { // log logs a message specific to this update context. func (i *invoiceUpdateCtx) log(s string) { log.Debugf("Invoice%v: %v, amt=%v, expiry=%v, circuit=%v, mpp=%v, "+ - "amp=%v", i.hash[:], s, i.amtPaid, i.expiry, i.circuitKey, + "amp=%v", i.invoiceRef(), s, i.amtPaid, i.expiry, i.circuitKey, i.mpp, i.amp) } From 7e2f5a184be09ab9265aecd183becd4e180ea333 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:48:51 -0700 Subject: [PATCH 09/22] channeldb: validate feature dependencies when adding invoice --- channeldb/invoice_test.go | 28 ++++++++++++++++++++++++++++ channeldb/invoices.go | 6 ++++++ invoices/test_utils_test.go | 10 ++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index af1d967b078..d17314023b8 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/lightningnetwork/lnd/clock" + "github.com/lightningnetwork/lnd/feature" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" @@ -1658,3 +1659,30 @@ func TestDeleteInvoices(t *testing.T) { assertInvoiceCount(0) } + +// TestAddInvoiceInvalidFeatureDeps asserts that inserting an invoice with +// invalid transitive feature dependencies fails with the appropriate error. +func TestAddInvoiceInvalidFeatureDeps(t *testing.T) { + t.Parallel() + + db, cleanup, err := MakeTestDB() + require.NoError(t, err, "unable to make test db") + defer cleanup() + + invoice, err := randInvoice(500) + require.NoError(t, err) + + invoice.Terms.Features = lnwire.NewFeatureVector( + lnwire.NewRawFeatureVector( + lnwire.TLVOnionPayloadOptional, + lnwire.MPPOptional, + ), + lnwire.Features, + ) + + hash := invoice.Terms.PaymentPreimage.Hash() + _, err = db.AddInvoice(invoice, hash) + require.Error(t, err, feature.NewErrMissingFeatureDep( + lnwire.PaymentAddrOptional, + )) +} diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 5a607ce95c8..a4ddd950dd7 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -10,6 +10,7 @@ import ( "time" "github.com/lightningnetwork/lnd/channeldb/kvdb" + "github.com/lightningnetwork/lnd/feature" "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -674,6 +675,11 @@ func validateInvoice(i *Invoice, paymentHash lntypes.Hash) error { return errors.New("invoice must have a feature vector") } + err := feature.ValidateDeps(i.Terms.Features) + if err != nil { + return err + } + if i.Terms.PaymentPreimage == nil && !i.HodlInvoice { return errors.New("non-hodl invoices must have a preimage") } diff --git a/invoices/test_utils_test.go b/invoices/test_utils_test.go index 73d41346582..0a2d8fa3387 100644 --- a/invoices/test_utils_test.go +++ b/invoices/test_utils_test.go @@ -111,7 +111,10 @@ var ( Value: testInvoiceAmt, Expiry: time.Hour, Features: lnwire.NewFeatureVector( - lnwire.NewRawFeatureVector(lnwire.PaymentAddrRequired), + lnwire.NewRawFeatureVector( + lnwire.TLVOnionPayloadOptional, + lnwire.PaymentAddrRequired, + ), lnwire.Features, ), }, @@ -124,7 +127,10 @@ var ( Value: testInvoiceAmt, Expiry: time.Hour, Features: lnwire.NewFeatureVector( - lnwire.NewRawFeatureVector(lnwire.PaymentAddrOptional), + lnwire.NewRawFeatureVector( + lnwire.TLVOnionPayloadOptional, + lnwire.PaymentAddrOptional, + ), lnwire.Features, ), }, From 3fb70dd936c03d769d8825029d0b3c328cefa0c5 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:48:59 -0700 Subject: [PATCH 10/22] invoices: add checkSettleResolution and checkFailResolution Also refactor existing unit tests to use them. --- invoices/invoiceregistry_test.go | 199 +++++++++---------------------- invoices/test_utils_test.go | 30 +++++ 2 files changed, 87 insertions(+), 142 deletions(-) diff --git a/invoices/invoiceregistry_test.go b/invoices/invoiceregistry_test.go index 2056a90173d..2f4e811a71b 100644 --- a/invoices/invoiceregistry_test.go +++ b/invoices/invoiceregistry_test.go @@ -75,19 +75,11 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatal(err) } - failResolution, ok := resolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - resolution) - } - if failResolution.AcceptHeight != testCurrentHeight { - t.Fatalf("expected acceptHeight %v, but got %v", - testCurrentHeight, failResolution.AcceptHeight) - } - if failResolution.Outcome != ResultExpiryTooSoon { - t.Fatalf("expected expiry too soon, got: %v", - failResolution.Outcome) - } + require.NotNil(t, resolution) + failResolution := checkFailResolution( + t, resolution, ResultExpiryTooSoon, + ) + require.Equal(t, testCurrentHeight, failResolution.AcceptHeight) // Settle invoice with a slightly higher amount. amtPaid := lnwire.MilliSatoshi(100500) @@ -99,15 +91,11 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatal(err) } - settleResolution, ok := resolution.(*HtlcSettleResolution) - if !ok { - t.Fatalf("expected settle resolution, got: %T", - resolution) - } - if settleResolution.Outcome != ResultSettled { - t.Fatalf("expected settled, got: %v", - settleResolution.Outcome) - } + require.NotNil(t, resolution) + settleResolution := checkSettleResolution( + t, resolution, testInvoicePreimage, + ) + require.Equal(t, ResultSettled, settleResolution.Outcome) // We expect the settled state to be sent to the single invoice // subscriber. @@ -144,15 +132,11 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err) } - settleResolution, ok = resolution.(*HtlcSettleResolution) - if !ok { - t.Fatalf("expected settle resolution, got: %T", - resolution) - } - if settleResolution.Outcome != ResultReplayToSettled { - t.Fatalf("expected replay settled, got: %v", - settleResolution.Outcome) - } + require.NotNil(t, resolution) + settleResolution = checkSettleResolution( + t, resolution, testInvoicePreimage, + ) + require.Equal(t, ResultReplayToSettled, settleResolution.Outcome) // Try to settle again with a new higher-valued htlc. This payment // should also be accepted, to prevent any change in behaviour for a @@ -164,15 +148,11 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err) } - settleResolution, ok = resolution.(*HtlcSettleResolution) - if !ok { - t.Fatalf("expected settle resolution, got: %T", - resolution) - } - if settleResolution.Outcome != ResultDuplicateToSettled { - t.Fatalf("expected duplicate settled, got: %v", - settleResolution.Outcome) - } + require.NotNil(t, resolution) + settleResolution = checkSettleResolution( + t, resolution, testInvoicePreimage, + ) + require.Equal(t, ResultDuplicateToSettled, settleResolution.Outcome) // Try to settle again with a lower amount. This should fail just as it // would have failed if it were the first payment. @@ -183,15 +163,8 @@ func TestSettleInvoice(t *testing.T) { if err != nil { t.Fatalf("unexpected NotifyExitHopHtlc error: %v", err) } - failResolution, ok = resolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - resolution) - } - if failResolution.Outcome != ResultAmountTooLow { - t.Fatalf("expected amount too low, got: %v", - failResolution.Outcome) - } + require.NotNil(t, resolution) + checkFailResolution(t, resolution, ResultAmountTooLow) // Check that settled amount is equal to the sum of values of the htlcs // 0 and 1. @@ -329,27 +302,23 @@ func testCancelInvoice(t *testing.T, gc bool) { if err != nil { t.Fatal("expected settlement of a canceled invoice to succeed") } - failResolution, ok := resolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - resolution) - } - if failResolution.AcceptHeight != testCurrentHeight { - t.Fatalf("expected acceptHeight %v, but got %v", - testCurrentHeight, failResolution.AcceptHeight) - } + require.NotNil(t, resolution) // If the invoice has been deleted (or not present) then we expect the // outcome to be ResultInvoiceNotFound instead of when the invoice is // in our database in which case we expect ResultInvoiceAlreadyCanceled. + var failResolution *HtlcFailResolution if gc { - require.Equal(t, failResolution.Outcome, ResultInvoiceNotFound) + failResolution = checkFailResolution( + t, resolution, ResultInvoiceNotFound, + ) } else { - require.Equal(t, - failResolution.Outcome, - ResultInvoiceAlreadyCanceled, + failResolution = checkFailResolution( + t, resolution, ResultInvoiceAlreadyCanceled, ) } + + require.Equal(t, testCurrentHeight, failResolution.AcceptHeight) } // TestCancelInvoice tests cancelation of an invoice and related notifications. @@ -474,15 +443,8 @@ func TestSettleHoldInvoice(t *testing.T) { if err != nil { t.Fatalf("expected settle to succeed but got %v", err) } - failResolution, ok := resolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - resolution) - } - if failResolution.Outcome != ResultExpiryTooSoon { - t.Fatalf("expected expiry too soon, got: %v", - failResolution.Outcome) - } + require.NotNil(t, resolution) + checkFailResolution(t, resolution, ResultExpiryTooSoon) // We expect the accepted state to be sent to the single invoice // subscriber. For all invoice subscribers, we don't expect an update. @@ -503,22 +465,12 @@ func TestSettleHoldInvoice(t *testing.T) { } htlcResolution := (<-hodlChan).(HtlcResolution) - settleResolution, ok := htlcResolution.(*HtlcSettleResolution) - if !ok { - t.Fatalf("expected settle resolution, got: %T", - htlcResolution) - } - if settleResolution.Preimage != testInvoicePreimage { - t.Fatal("unexpected preimage in hodl resolution") - } - if settleResolution.AcceptHeight != testCurrentHeight { - t.Fatalf("expected acceptHeight %v, but got %v", - testCurrentHeight, settleResolution.AcceptHeight) - } - if settleResolution.Outcome != ResultSettled { - t.Fatalf("expected result settled, got: %v", - settleResolution.Outcome) - } + require.NotNil(t, htlcResolution) + settleResolution := checkSettleResolution( + t, htlcResolution, testInvoicePreimage, + ) + require.Equal(t, testCurrentHeight, settleResolution.AcceptHeight) + require.Equal(t, ResultSettled, settleResolution.Outcome) // We expect a settled notification to be sent out for both all and // single invoice subscribers. @@ -604,11 +556,8 @@ func TestCancelHoldInvoice(t *testing.T) { } htlcResolution := (<-hodlChan).(HtlcResolution) - _, ok := htlcResolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - htlcResolution) - } + require.NotNil(t, htlcResolution) + checkFailResolution(t, htlcResolution, ResultCanceled) // Offering the same htlc again at a higher height should still result // in a rejection. The accept height is expected to be the original @@ -620,19 +569,11 @@ func TestCancelHoldInvoice(t *testing.T) { if err != nil { t.Fatalf("expected settle to succeed but got %v", err) } - failResolution, ok := resolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - resolution) - } - if failResolution.AcceptHeight != testCurrentHeight { - t.Fatalf("expected acceptHeight %v, but got %v", - testCurrentHeight, failResolution.AcceptHeight) - } - if failResolution.Outcome != ResultReplayToCanceled { - t.Fatalf("expected replay to canceled, got %v", - failResolution.Outcome) - } + require.NotNil(t, resolution) + failResolution := checkFailResolution( + t, resolution, ResultReplayToCanceled, + ) + require.Equal(t, testCurrentHeight, failResolution.AcceptHeight) } // TestUnknownInvoice tests that invoice registry returns an error when the @@ -655,15 +596,8 @@ func TestUnknownInvoice(t *testing.T) { if err != nil { t.Fatal("unexpected error") } - failResolution, ok := resolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - resolution) - } - if failResolution.Outcome != ResultInvoiceNotFound { - t.Fatalf("expected ResultInvoiceNotFound, got: %v", - failResolution.Outcome) - } + require.NotNil(t, resolution) + checkFailResolution(t, resolution, ResultInvoiceNotFound) } // TestKeySend tests receiving a spontaneous payment with and without keysend @@ -715,18 +649,12 @@ func testKeySend(t *testing.T, keySendEnabled bool) { if err != nil { t.Fatal(err) } - failResolution, ok := resolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - resolution) - } - - switch { - case !keySendEnabled && failResolution.Outcome != ResultInvoiceNotFound: - t.Fatal("expected invoice not found outcome") + require.NotNil(t, resolution) - case keySendEnabled && failResolution.Outcome != ResultKeySendError: - t.Fatal("expected keysend error") + if !keySendEnabled { + checkFailResolution(t, resolution, ResultInvoiceNotFound) + } else { + checkFailResolution(t, resolution, ResultKeySendError) } // Try to settle invoice with a valid keysend htlc. @@ -746,23 +674,10 @@ func testKeySend(t *testing.T, keySendEnabled bool) { // Expect a cancel resolution if keysend is disabled. if !keySendEnabled { - failResolution, ok = resolution.(*HtlcFailResolution) - if !ok { - t.Fatalf("expected fail resolution, got: %T", - resolution) - } - if failResolution.Outcome != ResultInvoiceNotFound { - t.Fatal("expected keysend payment not to be accepted") - } + checkFailResolution(t, resolution, ResultInvoiceNotFound) return } - checkResolution := func(res HtlcResolution, pimg lntypes.Preimage) { - // Otherwise we expect no error and a settle res for the htlc. - settleResolution, ok := res.(*HtlcSettleResolution) - require.True(t, ok) - require.Equal(t, settleResolution.Preimage, pimg) - } checkSubscription := func() { // We expect a new invoice notification to be sent out. newInvoice := <-allSubscriptions.NewInvoices @@ -773,7 +688,7 @@ func testKeySend(t *testing.T, keySendEnabled bool) { require.Equal(t, settledInvoice.State, channeldb.ContractSettled) } - checkResolution(resolution, preimage) + checkSettleResolution(t, resolution, preimage) checkSubscription() // Replay the same keysend payment. We expect an identical resolution, @@ -783,7 +698,7 @@ func testKeySend(t *testing.T, keySendEnabled bool) { testCurrentHeight, getCircuitKey(10), hodlChan, keySendPayload, ) require.Nil(t, err) - checkResolution(resolution, preimage) + checkSettleResolution(t, resolution, preimage) select { case <-allSubscriptions.NewInvoices: @@ -808,7 +723,7 @@ func testKeySend(t *testing.T, keySendEnabled bool) { ) require.Nil(t, err) - checkResolution(resolution, preimage2) + checkSettleResolution(t, resolution, preimage2) checkSubscription() } diff --git a/invoices/test_utils_test.go b/invoices/test_utils_test.go index 0a2d8fa3387..c51d3e7b1f9 100644 --- a/invoices/test_utils_test.go +++ b/invoices/test_utils_test.go @@ -19,6 +19,7 @@ import ( "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/zpay32" + "github.com/stretchr/testify/require" ) type mockPayload struct { @@ -331,3 +332,32 @@ func generateInvoiceExpiryTestData( return testData } + +// checkSettleResolution asserts the resolution is a settle with the correct +// preimage. If successful, the HtlcSettleResolution is returned in case further +// checks are desired. +func checkSettleResolution(t *testing.T, res HtlcResolution, + expPreimage lntypes.Preimage) *HtlcSettleResolution { + + t.Helper() + + settleResolution, ok := res.(*HtlcSettleResolution) + require.True(t, ok) + require.Equal(t, expPreimage, settleResolution.Preimage) + + return settleResolution +} + +// checkFailResolution asserts the resolution is a fail with the correct reason. +// If successful, the HtlcFailResolutionis returned in case further checks are +// desired. +func checkFailResolution(t *testing.T, res HtlcResolution, + expOutcome FailResolutionResult) *HtlcFailResolution { + + t.Helper() + failResolution, ok := res.(*HtlcFailResolution) + require.True(t, ok) + require.Equal(t, expOutcome, failResolution.Outcome) + + return failResolution +} From 88b72ab3983deae2ecd39100292964ffd1c1d3fc Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 22 Mar 2021 12:37:23 -0700 Subject: [PATCH 11/22] invoices: add processAMP --- invoices/invoiceregistry.go | 84 +++++++++++++++++++++++++++++--- invoices/invoiceregistry_test.go | 33 +++++++++++++ invoices/resolution_result.go | 6 +++ invoices/test_utils_test.go | 18 ++++--- 4 files changed, 127 insertions(+), 14 deletions(-) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 4f594ee4121..a9cf82a8eaf 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -781,6 +781,67 @@ func (i *InvoiceRegistry) processKeySend(ctx invoiceUpdateCtx) error { return nil } +// processAMP just-in-time inserts an invoice if this htlc is a keysend +// htlc. +func (i *InvoiceRegistry) processAMP(ctx invoiceUpdateCtx) error { + // AMP payments MUST also include an MPP record. + if ctx.mpp == nil { + return errors.New("no MPP record for AMP") + } + + // Create an invoice for the total amount expected, provided in the MPP + // record. + amt := ctx.mpp.TotalMsat() + + // Set the TLV and MPP optional features on the invoice. We'll also make + // the AMP features required so that it can't be paid by legacy or MPP + // htlcs. + rawFeatures := lnwire.NewRawFeatureVector( + lnwire.TLVOnionPayloadOptional, + lnwire.PaymentAddrOptional, + lnwire.AMPRequired, + ) + features := lnwire.NewFeatureVector(rawFeatures, lnwire.Features) + + // Use the minimum block delta that we require for settling htlcs. + finalCltvDelta := i.cfg.FinalCltvRejectDelta + + // Pre-check expiry here to prevent inserting an invoice that will not + // be settled. + if ctx.expiry < uint32(ctx.currentHeight+finalCltvDelta) { + return errors.New("final expiry too soon") + } + + // We'll use the sender-generated payment address provided in the HTLC + // to create our AMP invoice. + payAddr := ctx.mpp.PaymentAddr() + + // Create placeholder invoice. + invoice := &channeldb.Invoice{ + CreationDate: i.cfg.Clock.Now(), + Terms: channeldb.ContractTerm{ + FinalCltvDelta: finalCltvDelta, + Value: amt, + PaymentPreimage: nil, + PaymentAddr: payAddr, + Features: features, + }, + } + + // Insert invoice into database. Ignore duplicates payment hashes and + // payment addrs, this may be a replay or a different HTLC for the AMP + // invoice. + _, err := i.AddInvoice(invoice, ctx.hash) + switch { + case err == channeldb.ErrDuplicateInvoice: + return nil + case err == channeldb.ErrDuplicatePayAddr: + return nil + default: + return err + } +} + // NotifyExitHopHtlc attempts to mark an invoice as settled. The return value // describes how the htlc should be resolved. // @@ -819,13 +880,24 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash, // AddInvoice obtains its own lock. This is no problem, because the // operation is idempotent. if i.cfg.AcceptKeySend { - err := i.processKeySend(ctx) - if err != nil { - ctx.log(fmt.Sprintf("keysend error: %v", err)) + if ctx.amp != nil { + err := i.processAMP(ctx) + if err != nil { + ctx.log(fmt.Sprintf("amp error: %v", err)) - return NewFailResolution( - circuitKey, currentHeight, ResultKeySendError, - ), nil + return NewFailResolution( + circuitKey, currentHeight, ResultAmpError, + ), nil + } + } else { + err := i.processKeySend(ctx) + if err != nil { + ctx.log(fmt.Sprintf("keysend error: %v", err)) + + return NewFailResolution( + circuitKey, currentHeight, ResultKeySendError, + ), nil + } } } diff --git a/invoices/invoiceregistry_test.go b/invoices/invoiceregistry_test.go index 2f4e811a71b..e27a60c7342 100644 --- a/invoices/invoiceregistry_test.go +++ b/invoices/invoiceregistry_test.go @@ -1273,3 +1273,36 @@ func TestSettleInvoicePaymentAddrRequiredOptionalGrace(t *testing.T) { t.Fatal("no update received") } } + +// TestAMPWithoutMPPPayload asserts that we correctly reject an AMP HTLC that +// does not include an MPP record. +func TestAMPWithoutMPPPayload(t *testing.T) { + defer timeout()() + + ctx := newTestContext(t) + defer ctx.cleanup() + + ctx.registry.cfg.AcceptKeySend = true + + const ( + shardAmt = lnwire.MilliSatoshi(10) + expiry = uint32(testCurrentHeight + 20) + ) + + // Create payload with missing MPP field. + payload := &mockPayload{ + amp: record.NewAMP([32]byte{}, [32]byte{}, 0), + } + + hodlChan := make(chan interface{}, 1) + resolution, err := ctx.registry.NotifyExitHopHtlc( + lntypes.Hash{}, shardAmt, expiry, + testCurrentHeight, getCircuitKey(uint64(10)), hodlChan, + payload, + ) + require.NoError(t, err) + + // We should receive the ResultAmpError failure. + require.NotNil(t, resolution) + checkFailResolution(t, resolution, ResultAmpError) +} diff --git a/invoices/resolution_result.go b/invoices/resolution_result.go index b979d3ac0ac..0aa2f64652f 100644 --- a/invoices/resolution_result.go +++ b/invoices/resolution_result.go @@ -105,6 +105,9 @@ const ( // ResultMppInProgress is returned when we are busy receiving a mpp // payment. ResultMppInProgress + + // ResultAmpError is returned when we receive invalid AMP parameters. + ResultAmpError ) // String returns a string representation of the result. @@ -162,6 +165,9 @@ func (f FailResolutionResult) FailureString() string { case ResultMppInProgress: return "mpp reception in progress" + case ResultAmpError: + return "invalid amp parameters" + default: return "unknown failure resolution result" } diff --git a/invoices/test_utils_test.go b/invoices/test_utils_test.go index c51d3e7b1f9..6a454a9ea03 100644 --- a/invoices/test_utils_test.go +++ b/invoices/test_utils_test.go @@ -46,6 +46,16 @@ func (p *mockPayload) CustomRecords() record.CustomSet { return p.customRecords } +const ( + testHtlcExpiry = uint32(5) + + testInvoiceCltvDelta = uint32(4) + + testFinalCltvRejectDelta = int32(4) + + testCurrentHeight = int32(1) +) + var ( testTimeout = 5 * time.Second @@ -55,14 +65,6 @@ var ( testInvoicePaymentHash = testInvoicePreimage.Hash() - testHtlcExpiry = uint32(5) - - testInvoiceCltvDelta = uint32(4) - - testFinalCltvRejectDelta = int32(4) - - testCurrentHeight = int32(1) - testPrivKeyBytes, _ = hex.DecodeString( "e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734") From 24d283e6156797bc1437cf0b5b64e06754db737c Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:50:44 -0700 Subject: [PATCH 12/22] channeldb/invoice_test: only set htlc-level preimage on accept --- channeldb/invoice_test.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index d17314023b8..0b27d8dfeb2 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -1374,7 +1374,7 @@ func TestSetIDIndex(t *testing.T) { invoice.AmtPaid = amt invoice.SettleDate = dbInvoice.SettleDate invoice.Htlcs = map[CircuitKey]*InvoiceHTLC{ - {HtlcID: 0}: makeAMPInvoiceHTLC(amt, *setID, preimage), + {HtlcID: 0}: makeAMPInvoiceHTLC(amt, *setID, payHash, &preimage), } // We should get back the exact same invoice that we just inserted. @@ -1414,9 +1414,9 @@ func TestSetIDIndex(t *testing.T) { invoice.AmtPaid += 2 * amt invoice.SettleDate = dbInvoice.SettleDate invoice.Htlcs = map[CircuitKey]*InvoiceHTLC{ - {HtlcID: 0}: makeAMPInvoiceHTLC(amt, *setID, preimage), - {HtlcID: 1}: makeAMPInvoiceHTLC(amt, *setID2, preimage), - {HtlcID: 2}: makeAMPInvoiceHTLC(amt, *setID2, preimage), + {HtlcID: 0}: makeAMPInvoiceHTLC(amt, *setID, payHash, &preimage), + {HtlcID: 1}: makeAMPInvoiceHTLC(amt, *setID2, payHash, nil), + {HtlcID: 2}: makeAMPInvoiceHTLC(amt, *setID2, payHash, nil), } // We should get back the exact same invoice that we just inserted. @@ -1460,7 +1460,7 @@ func TestSetIDIndex(t *testing.T) { } func makeAMPInvoiceHTLC(amt lnwire.MilliSatoshi, setID [32]byte, - preimage lntypes.Preimage) *InvoiceHTLC { + hash lntypes.Hash, preimage *lntypes.Preimage) *InvoiceHTLC { return &InvoiceHTLC{ Amt: amt, @@ -1470,8 +1470,8 @@ func makeAMPInvoiceHTLC(amt lnwire.MilliSatoshi, setID [32]byte, CustomRecords: make(record.CustomSet), AMP: &InvoiceHtlcAMPData{ Record: *record.NewAMP([32]byte{}, setID, 0), - Hash: preimage.Hash(), - Preimage: &preimage, + Hash: hash, + Preimage: preimage, }, } } @@ -1488,18 +1488,23 @@ func updateAcceptAMPHtlc(id uint64, amt lnwire.MilliSatoshi, noRecords := make(record.CustomSet) - var state *InvoiceStateUpdateDesc + var ( + state *InvoiceStateUpdateDesc + preimage *lntypes.Preimage + ) if accept { state = &InvoiceStateUpdateDesc{ NewState: ContractAccepted, SetID: setID, } + pre := *invoice.Terms.PaymentPreimage + preimage = &pre } ampData := &InvoiceHtlcAMPData{ Record: *record.NewAMP([32]byte{}, *setID, 0), Hash: invoice.Terms.PaymentPreimage.Hash(), - Preimage: invoice.Terms.PaymentPreimage, + Preimage: preimage, } update := &InvoiceUpdateDesc{ State: state, From 6780f74c8730e54b012ce0e5ccdd811848e9b868 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:51:03 -0700 Subject: [PATCH 13/22] channeldb/invoices: set AMP HTLC preimages when settling invoice --- channeldb/invoice_test.go | 99 ++++++++++++++++++++++++++++++++++++++- channeldb/invoices.go | 31 +++++++++++- 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index 0b27d8dfeb2..510e0802d9d 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -17,7 +17,15 @@ import ( var ( emptyFeatures = lnwire.NewFeatureVector(nil, lnwire.Features) - testNow = time.Unix(1, 0) + ampFeatures = lnwire.NewFeatureVector( + lnwire.NewRawFeatureVector( + lnwire.TLVOnionPayloadOptional, + lnwire.PaymentAddrOptional, + lnwire.AMPRequired, + ), + lnwire.Features, + ) + testNow = time.Unix(1, 0) ) func randInvoice(value lnwire.MilliSatoshi) (*Invoice, error) { @@ -1571,6 +1579,95 @@ func TestUnexpectedInvoicePreimage(t *testing.T) { require.Error(t, ErrUnexpectedInvoicePreimage, err) } +type updateHTLCPreimageTestCase struct { + name string + settleSamePreimage bool + expError error +} + +// TestUpdateHTLCPreimages asserts various properties of setting HTLC-level +// preimages on invoice state transitions. +func TestUpdateHTLCPreimages(t *testing.T) { + t.Parallel() + + tests := []updateHTLCPreimageTestCase{ + { + name: "same preimage on settle", + settleSamePreimage: true, + expError: nil, + }, + { + name: "diff preimage on settle", + settleSamePreimage: false, + expError: ErrHTLCPreimageAlreadyExists, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + testUpdateHTLCPreimages(t, test) + }) + } +} + +func testUpdateHTLCPreimages(t *testing.T, test updateHTLCPreimageTestCase) { + db, cleanup, err := MakeTestDB() + defer cleanup() + require.NoError(t, err, "unable to make test db") + + // We'll start out by creating an invoice and writing it to the DB. + amt := lnwire.NewMSatFromSatoshis(1000) + invoice, err := randInvoice(amt) + require.Nil(t, err) + + preimage := *invoice.Terms.PaymentPreimage + payHash := preimage.Hash() + + // Set AMP-specific features so that we can settle with HTLC-level + // preimages. + invoice.Terms.Features = ampFeatures + + _, err = db.AddInvoice(invoice, payHash) + require.Nil(t, err) + + setID := &[32]byte{1} + + // Update the invoice with an accepted HTLC that also accepts the + // invoice. + ref := InvoiceRefByAddr(invoice.Terms.PaymentAddr) + dbInvoice, err := db.UpdateInvoice(ref, updateAcceptAMPHtlc(0, amt, setID, true)) + require.Nil(t, err) + + htlcPreimages := make(map[CircuitKey]lntypes.Preimage) + for key := range dbInvoice.Htlcs { + // Set the either the same preimage used to accept above, or a + // blank preimage depending on the test case. + var pre lntypes.Preimage + if test.settleSamePreimage { + pre = preimage + } + htlcPreimages[key] = pre + } + + updateInvoice := func(invoice *Invoice) (*InvoiceUpdateDesc, error) { + update := &InvoiceUpdateDesc{ + State: &InvoiceStateUpdateDesc{ + Preimage: nil, + NewState: ContractSettled, + HTLCPreimages: htlcPreimages, + SetID: setID, + }, + } + + return update, nil + } + + // Now settle the HTLC set and assert the resulting error. + _, err = db.UpdateInvoice(ref, updateInvoice) + require.Equal(t, test.expError, err) +} + // TestDeleteInvoices tests that deleting a list of invoices will succeed // if all delete references are valid, or will fail otherwise. func TestDeleteInvoices(t *testing.T) { diff --git a/channeldb/invoices.go b/channeldb/invoices.go index a4ddd950dd7..6d6c4d5cf81 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -131,6 +131,12 @@ var ( ErrUnexpectedInvoicePreimage = errors.New( "unexpected invoice preimage provided on settle", ) + + // ErrHTLCPreimageAlreadyExists is returned when trying to set an + // htlc-level preimage but one is already known. + ErrHTLCPreimageAlreadyExists = errors.New( + "htlc-level preimage already exists", + ) ) // ErrDuplicateSetID is an error returned when attempting to adding an AMP HTLC @@ -646,6 +652,11 @@ type InvoiceStateUpdateDesc struct { // Preimage must be set to the preimage when NewState is settled. Preimage *lntypes.Preimage + // HTLCPreimages set the HTLC-level preimages stored for AMP HTLCs. + // These are only learned when settling the invoice as a whole. Must be + // set when settling an invoice with non-nil SetID. + HTLCPreimages map[CircuitKey]lntypes.Preimage + // SetID identifies a specific set of HTLCs destined for the same // invoice as part of a larger AMP payment. This value will be nil for // legacy or MPP payments. @@ -1914,7 +1925,25 @@ func (d *DB) updateInvoice(hash *lntypes.Hash, invoices, // the process by updating the state transitions for individual HTLCs // and recalculate the total amount paid to the invoice. var amtPaid lnwire.MilliSatoshi - for _, htlc := range invoice.Htlcs { + for key, htlc := range invoice.Htlcs { + // Set the HTLC preimage for any AMP HTLCs. + if setID != nil { + preimage, ok := update.State.HTLCPreimages[key] + switch { + + // If we don't already have a preiamge for this HTLC, we + // can set it now. + case ok && htlc.AMP.Preimage == nil: + htlc.AMP.Preimage = &preimage + + // Otherwise, prevent over-writing an existing preimage. + // Ignore the case where the preimage is identical. + case ok && *htlc.AMP.Preimage != preimage: + return nil, ErrHTLCPreimageAlreadyExists + + } + } + // The invoice state may have changed and this could have // implications for the states of the individual htlcs. Align // the htlc state with the current invoice state. From 0b5be8576e34f3cd8e5a18b1c01d1ade70d8c98c Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:51:22 -0700 Subject: [PATCH 14/22] channeldb/invoice: make Copy() a member of InvoiceHTLC --- channeldb/invoices.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 6d6c4d5cf81..5daee5ffa8a 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -535,6 +535,21 @@ type InvoiceHTLC struct { AMP *InvoiceHtlcAMPData } +// Copy makes a deep copy of the target InvoiceHTLC. +func (h *InvoiceHTLC) Copy() *InvoiceHTLC { + result := *h + + // Make a copy of the CustomSet map. + result.CustomRecords = make(record.CustomSet) + for k, v := range h.CustomRecords { + result.CustomRecords[k] = v + } + + result.AMP = h.AMP.Copy() + + return &result +} + // IsInHTLCSet returns true if this HTLC is part an HTLC set. If nil is passed, // this method returns true if this is an MPP HTLC. Otherwise, it only returns // true if the AMP HTLC's set id matches the populated setID. @@ -1742,21 +1757,6 @@ func copySlice(src []byte) []byte { return dest } -// copyInvoiceHTLC makes a deep copy of the supplied invoice HTLC. -func copyInvoiceHTLC(src *InvoiceHTLC) *InvoiceHTLC { - result := *src - - // Make a copy of the CustomSet map. - result.CustomRecords = make(record.CustomSet) - for k, v := range src.CustomRecords { - result.CustomRecords[k] = v - } - - result.AMP = src.AMP.Copy() - - return &result -} - // copyInvoice makes a deep copy of the supplied invoice. func copyInvoice(src *Invoice) *Invoice { dest := Invoice{ @@ -1783,7 +1783,7 @@ func copyInvoice(src *Invoice) *Invoice { } for k, v := range src.Htlcs { - dest.Htlcs[k] = copyInvoiceHTLC(v) + dest.Htlcs[k] = v.Copy() } return &dest From 2a49b59f4f98a13c74c26499fce0df324f7b615f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:51:41 -0700 Subject: [PATCH 15/22] channeldb/invoices: rigorously test updateHtlc for MPP/AMP scenarios --- channeldb/invoice_test.go | 665 ++++++++++++++++++++++++++++++++++++++ channeldb/invoices.go | 39 ++- 2 files changed, 698 insertions(+), 6 deletions(-) diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index 510e0802d9d..61806d39c12 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -1668,6 +1668,671 @@ func testUpdateHTLCPreimages(t *testing.T, test updateHTLCPreimageTestCase) { require.Equal(t, test.expError, err) } +type updateHTLCTest struct { + name string + input InvoiceHTLC + invState ContractState + setID *[32]byte + output InvoiceHTLC + expErr error +} + +// TestUpdateHTLC asserts the behavior of the updateHTLC method in various +// scenarios for MPP and AMP. +func TestUpdateHTLC(t *testing.T) { + t.Parallel() + + setID := [32]byte{0x01} + ampRecord := record.NewAMP([32]byte{0x02}, setID, 3) + preimage := lntypes.Preimage{0x04} + hash := preimage.Hash() + + diffSetID := [32]byte{0x05} + fakePreimage := lntypes.Preimage{0x06} + testAlreadyNow := time.Now() + + tests := []updateHTLCTest{ + { + name: "MPP accept", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: nil, + }, + invState: ContractAccepted, + setID: nil, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: nil, + }, + expErr: nil, + }, + { + name: "MPP settle", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: nil, + }, + invState: ContractSettled, + setID: nil, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testNow, + Expiry: 40, + State: HtlcStateSettled, + CustomRecords: make(record.CustomSet), + AMP: nil, + }, + expErr: nil, + }, + { + name: "MPP cancel", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: nil, + }, + invState: ContractCanceled, + setID: nil, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: nil, + }, + expErr: nil, + }, + { + name: "AMP accept missing preimage", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: nil, + }, + }, + invState: ContractAccepted, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: nil, + }, + }, + expErr: ErrHTLCPreimageMissing, + }, + { + name: "AMP accept invalid preimage", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &fakePreimage, + }, + }, + invState: ContractAccepted, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &fakePreimage, + }, + }, + expErr: ErrHTLCPreimageMismatch, + }, + { + name: "AMP accept valid preimage", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractAccepted, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + { + name: "AMP accept valid preimage different htlc set", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractAccepted, + setID: &diffSetID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + { + name: "AMP settle missing preimage", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: nil, + }, + }, + invState: ContractSettled, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: nil, + }, + }, + expErr: ErrHTLCPreimageMissing, + }, + { + name: "AMP settle invalid preimage", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &fakePreimage, + }, + }, + invState: ContractSettled, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &fakePreimage, + }, + }, + expErr: ErrHTLCPreimageMismatch, + }, + { + name: "AMP settle valid preimage", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractSettled, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testNow, + Expiry: 40, + State: HtlcStateSettled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + { + name: "AMP settle valid preimage different htlc set", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractSettled, + setID: &diffSetID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + { + name: "accept invoice htlc already settled", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateSettled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractAccepted, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateSettled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: ErrHTLCAlreadySettled, + }, + { + name: "cancel invoice htlc already settled", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateSettled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractCanceled, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateSettled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: ErrHTLCAlreadySettled, + }, + { + name: "settle invoice htlc already settled", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateSettled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractSettled, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateSettled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + { + name: "cancel invoice", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: time.Time{}, + Expiry: 40, + State: HtlcStateAccepted, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractCanceled, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + { + name: "accept invoice htlc already canceled", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractAccepted, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + { + name: "cancel invoice htlc already canceled", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractCanceled, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + { + name: "settle invoice htlc already canceled", + input: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + invState: ContractSettled, + setID: &setID, + output: InvoiceHTLC{ + Amt: 5000, + MppTotalAmt: 5000, + AcceptHeight: 100, + AcceptTime: testNow, + ResolveTime: testAlreadyNow, + Expiry: 40, + State: HtlcStateCanceled, + CustomRecords: make(record.CustomSet), + AMP: &InvoiceHtlcAMPData{ + Record: *ampRecord, + Hash: hash, + Preimage: &preimage, + }, + }, + expErr: nil, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + testUpdateHTLC(t, test) + }) + } +} + +func testUpdateHTLC(t *testing.T, test updateHTLCTest) { + htlc := test.input.Copy() + err := updateHtlc(testNow, htlc, test.invState, test.setID) + require.Equal(t, test.expErr, err) + require.Equal(t, test.output, *htlc) +} + // TestDeleteInvoices tests that deleting a list of invoices will succeed // if all delete references are valid, or will fail otherwise. func TestDeleteInvoices(t *testing.T) { diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 5daee5ffa8a..2dcd1be87da 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -117,6 +117,19 @@ var ( // match the invoice hash. ErrInvoicePreimageMismatch = errors.New("preimage does not match") + // ErrHTLCPreimageMissing is returned when trying to accept/settle an + // AMP HTLC but the HTLC-level preimage has not been set. + ErrHTLCPreimageMissing = errors.New("AMP htlc missing preimage") + + // ErrHTLCPreimageMismatch is returned when trying to accept/settle an + // AMP HTLC but the HTLC-level preimage does not satisfying the + // HTLC-level payment hash. + ErrHTLCPreimageMismatch = errors.New("htlc preimage mismatch") + + // ErrHTLCAlreadySettled is returned when trying to settle an invoice + // but HTLC already exists in the settled state. + ErrHTLCAlreadySettled = errors.New("htlc already settled") + // ErrInvoiceHasHtlcs is returned when attempting to insert an invoice // that already has HTLCs. ErrInvoiceHasHtlcs = errors.New("cannot add invoice with htlcs") @@ -2108,10 +2121,25 @@ func updateHtlc(resolveTime time.Time, htlc *InvoiceHTLC, // already know the preimage is valid due to checks at // the invoice level. For AMP HTLCs, verify that the // per-HTLC preimage-hash pair is valid. - if setID != nil && !htlc.AMP.Preimage.Matches(htlc.AMP.Hash) { - return fmt.Errorf("AMP preimage mismatch, "+ - "preimage=%v hash=%v", *htlc.AMP.Preimage, - htlc.AMP.Hash) + switch { + + // Non-AMP HTLCs can be settle immediately since we + // already know the preimage is valid due to checks at + // the invoice level. + case setID == nil: + + // At this popint, the setID is non-nil, meaning this is + // an AMP HTLC. We know that htlc.AMP cannot be nil, + // otherwise IsInHTLCSet would have returned false. + // + // Fail if an accepted AMP HTLC has no preimage. + case htlc.AMP.Preimage == nil: + return ErrHTLCPreimageMissing + + // Fail if the accepted AMP HTLC has an invalid + // preimage. + case !htlc.AMP.Preimage.Matches(htlc.AMP.Hash): + return ErrHTLCPreimageMismatch } htlcState = HtlcStateSettled @@ -2140,8 +2168,7 @@ func updateHtlc(resolveTime time.Time, htlc *InvoiceHTLC, // We should never find a settled HTLC on an invoice that isn't in // ContractSettled. if htlc.State == HtlcStateSettled { - return fmt.Errorf("cannot have a settled htlc with "+ - "invoice in state %v", invState) + return ErrHTLCAlreadySettled } switch invState { From 90a255078d7094893a6ee1c786a40d8323bb0c30 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:52:01 -0700 Subject: [PATCH 16/22] invoices: reconstruct AMP child preimages --- invoices/invoiceregistry.go | 7 +- invoices/resolution_result.go | 7 ++ invoices/update.go | 133 +++++++++++++++++++++++++++++++--- 3 files changed, 137 insertions(+), 10 deletions(-) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index a9cf82a8eaf..db72243fc89 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -1019,13 +1019,18 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( continue } + preimage := res.Preimage + if htlc.AMP != nil && htlc.AMP.Preimage != nil { + preimage = *htlc.AMP.Preimage + } + // Notify subscribers that the htlcs should be settled // with our peer. Note that the outcome of the // resolution is set based on the outcome of the single // htlc that we just settled, so may not be accurate // for all htlcs. htlcSettleResolution := NewSettleResolution( - res.Preimage, key, + preimage, key, int32(htlc.AcceptHeight), res.Outcome, ) diff --git a/invoices/resolution_result.go b/invoices/resolution_result.go index 0aa2f64652f..fc95661f47f 100644 --- a/invoices/resolution_result.go +++ b/invoices/resolution_result.go @@ -108,6 +108,10 @@ const ( // ResultAmpError is returned when we receive invalid AMP parameters. ResultAmpError + + // ResultAmpReconstruction is returned when the derived child + // hash/preimage pairs were invalid for at least one HTLC in the set. + ResultAmpReconstruction ) // String returns a string representation of the result. @@ -168,6 +172,9 @@ func (f FailResolutionResult) FailureString() string { case ResultAmpError: return "invalid amp parameters" + case ResultAmpReconstruction: + return "amp reconstruction failed" + default: return "unknown failure resolution result" } diff --git a/invoices/update.go b/invoices/update.go index c656914328c..e10b92c6770 100644 --- a/invoices/update.go +++ b/invoices/update.go @@ -3,6 +3,7 @@ package invoices import ( "errors" + "github.com/lightningnetwork/lnd/amp" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -26,11 +27,16 @@ type invoiceUpdateCtx struct { // invoiceRef returns an identifier that can be used to lookup or update the // invoice this HTLC is targeting. func (i *invoiceUpdateCtx) invoiceRef() channeldb.InvoiceRef { - if i.mpp != nil { + switch { + case i.amp != nil && i.mpp != nil: + payAddr := i.mpp.PaymentAddr() + return channeldb.InvoiceRefByAddr(payAddr) + case i.mpp != nil: payAddr := i.mpp.PaymentAddr() return channeldb.InvoiceRefByHashAndAddr(i.hash, payAddr) + default: + return channeldb.InvoiceRefByHash(i.hash) } - return channeldb.InvoiceRefByHash(i.hash) } // setID returns an identifier that identifies other possible HTLCs that this @@ -130,6 +136,14 @@ func updateMpp(ctx *invoiceUpdateCtx, CustomRecords: ctx.customRecords, } + if ctx.amp != nil { + acceptDesc.AMP = &channeldb.InvoiceHtlcAMPData{ + Record: *ctx.amp, + Hash: ctx.hash, + Preimage: nil, + } + } + // Only accept payments to open invoices. This behaviour differs from // non-mpp payments that are accepted even after the invoice is settled. // Because non-mpp payments don't have a payment address, this is needed @@ -154,9 +168,18 @@ func updateMpp(ctx *invoiceUpdateCtx, return nil, ctx.failRes(ResultHtlcSetTotalTooLow), nil } + htlcSet := inv.HTLCSet(setID) + // Check whether total amt matches other htlcs in the set. var newSetTotal lnwire.MilliSatoshi - for _, htlc := range inv.HTLCSet(setID) { + for _, htlc := range htlcSet { + // Only consider accepted mpp htlcs. It is possible that there + // are htlcs registered in the invoice database that previously + // timed out and are in the canceled state now. + if htlc.State != channeldb.HtlcStateAccepted { + continue + } + if ctx.mpp.TotalMsat() != htlc.MppTotalAmt { return nil, ctx.failRes(ResultHtlcSetTotalMismatch), nil } @@ -206,15 +229,107 @@ func updateMpp(ctx *invoiceUpdateCtx, return &update, ctx.acceptRes(resultAccepted), nil } + var ( + htlcPreimages map[channeldb.CircuitKey]lntypes.Preimage + htlcPreimage lntypes.Preimage + ) + if ctx.amp != nil { + var failRes *HtlcFailResolution + htlcPreimages, failRes = reconstructAMPPreimages(ctx, htlcSet) + if failRes != nil { + update.State = &channeldb.InvoiceStateUpdateDesc{ + NewState: channeldb.ContractCanceled, + SetID: setID, + } + return &update, failRes, nil + } + + // The preimage for _this_ HTLC will be the one with context's + // circuit key. + htlcPreimage = htlcPreimages[ctx.circuitKey] + } else { + htlcPreimage = *inv.Terms.PaymentPreimage + } + update.State = &channeldb.InvoiceStateUpdateDesc{ - NewState: channeldb.ContractSettled, - Preimage: inv.Terms.PaymentPreimage, - SetID: setID, + NewState: channeldb.ContractSettled, + Preimage: inv.Terms.PaymentPreimage, + HTLCPreimages: htlcPreimages, + SetID: setID, } - return &update, ctx.settleRes( - *inv.Terms.PaymentPreimage, ResultSettled, - ), nil + return &update, ctx.settleRes(htlcPreimage, ResultSettled), nil +} + +// HTLCSet is a map of CircuitKey to InvoiceHTLC. +type HTLCSet = map[channeldb.CircuitKey]*channeldb.InvoiceHTLC + +// HTLCPreimages is a map of CircuitKey to preimage. +type HTLCPreimages = map[channeldb.CircuitKey]lntypes.Preimage + +// reconstructAMPPreimages reconstructs the root seed for an AMP HTLC set and +// verifies that all derived child hashes match the payment hashes of the HTLCs +// in the set. This method is meant to be called after receiving the full amount +// committed to via mpp_total_msat. This method will return a fail resolution if +// any of the child hashes fail to matche theire corresponding HTLCs. +func reconstructAMPPreimages(ctx *invoiceUpdateCtx, + htlcSet HTLCSet) (HTLCPreimages, *HtlcFailResolution) { + + // Create a slice containing all the child descriptors to be used for + // reconstruction. This should include all HTLCs currently in the HTLC + // set, plus the incoming HTLC. + childDescs := make([]amp.ChildDesc, 0, 1+len(htlcSet)) + + // Add the new HTLC's child descriptor at index 0. + childDescs = append(childDescs, amp.ChildDesc{ + Share: ctx.amp.RootShare(), + Index: ctx.amp.ChildIndex(), + }) + + // Next, construct an index mapping the position in childDescs to a + // circuit key for all preexisting HTLCs. + indexToCircuitKey := make(map[int]channeldb.CircuitKey) + + // Add the child descriptor for each HTLC in the HTLC set, recording + // it's position within the slice. + var htlcSetIndex int + for circuitKey, htlc := range htlcSet { + childDescs = append(childDescs, amp.ChildDesc{ + Share: htlc.AMP.Record.RootShare(), + Index: htlc.AMP.Record.ChildIndex(), + }) + indexToCircuitKey[htlcSetIndex] = circuitKey + htlcSetIndex++ + } + + // Using the child descriptors, reconstruct the root seed and derive the + // child hash/preimage pairs for each of the HTLCs. + children := amp.ReconstructChildren(childDescs...) + + // Validate that the derived child preimages match the hash of each + // HTLC's respective hash. + if ctx.hash != children[0].Hash { + return nil, ctx.failRes(ResultAmpReconstruction) + } + for idx, child := range children[1:] { + circuitKey := indexToCircuitKey[idx] + htlc := htlcSet[circuitKey] + if htlc.AMP.Hash != child.Hash { + return nil, ctx.failRes(ResultAmpReconstruction) + } + } + + // Finally, construct the map of learned preimages indexed by circuit + // key, so that they can be persisted along with each HTLC when updating + // the invoice. + htlcPreimages := make(map[channeldb.CircuitKey]lntypes.Preimage) + htlcPreimages[ctx.circuitKey] = children[0].Preimage + for idx, child := range children[1:] { + circuitKey := indexToCircuitKey[idx] + htlcPreimages[circuitKey] = child.Preimage + } + + return htlcPreimages, nil } // updateLegacy is a callback for DB.UpdateInvoice that contains the invoice From ea934e1be9b7eef37b830e469684152d6ce387af Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:52:18 -0700 Subject: [PATCH 17/22] invoices: add TestSpontaneousAmpPayment Adds a set of test cases that exercise the spontaneous AMP payment flow with valid and invalid reconstructions, as well as with single and multiple HTLCs. This also asserts that spontaneous AMP is gated behind the existing AcceptKeysend flag. --- invoices/invoiceregistry.go | 25 ++++ invoices/invoiceregistry_test.go | 220 +++++++++++++++++++++++++++++++ invoices/resolution_result.go | 17 +++ 3 files changed, 262 insertions(+) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index db72243fc89..b73de5e503d 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -1004,6 +1004,31 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( "outcome: %v, at accept height: %v", res.Outcome, res.AcceptHeight)) + // Some failures apply to the entire HTLC set. Break here if + // this isn't one of them. + if !res.Outcome.IsSetFailure() { + break + } + + // Also cancel any HTLCs in the HTLC set that are also in the + // canceled state with the same failure result. + setID := ctx.setID() + for key, htlc := range invoice.Htlcs { + if htlc.State != channeldb.HtlcStateCanceled { + continue + } + + if !htlc.IsInHTLCSet(setID) { + continue + } + + htlcFailResolution := NewFailResolution( + key, int32(htlc.AcceptHeight), res.Outcome, + ) + + i.notifyHodlSubscribers(htlcFailResolution) + } + // If the htlc was settled, we will settle any previously accepted // htlcs and notify our peer to settle them. case *HtlcSettleResolution: diff --git a/invoices/invoiceregistry_test.go b/invoices/invoiceregistry_test.go index e27a60c7342..1d1198ebdda 100644 --- a/invoices/invoiceregistry_test.go +++ b/invoices/invoiceregistry_test.go @@ -1,10 +1,12 @@ package invoices import ( + "crypto/rand" "math" "testing" "time" + "github.com/lightningnetwork/lnd/amp" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lntypes" @@ -1306,3 +1308,221 @@ func TestAMPWithoutMPPPayload(t *testing.T) { require.NotNil(t, resolution) checkFailResolution(t, resolution, ResultAmpError) } + +// TestSpontaneousAmpPayment tests receiving a spontaneous AMP payment with both +// valid and invalid reconstructions. +func TestSpontaneousAmpPayment(t *testing.T) { + tests := []struct { + name string + keySendEnabled bool + failReconstruction bool + numShards int + }{ + { + name: "enabled valid one shard", + keySendEnabled: true, + failReconstruction: false, + numShards: 1, + }, + { + name: "enabled valid multiple shards", + keySendEnabled: true, + failReconstruction: false, + numShards: 3, + }, + { + name: "enabled invalid one shard", + keySendEnabled: true, + failReconstruction: true, + numShards: 1, + }, + { + name: "enabled invalid multiple shards", + keySendEnabled: true, + failReconstruction: true, + numShards: 3, + }, + { + name: "disabled valid multiple shards", + keySendEnabled: false, + failReconstruction: false, + numShards: 3, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + testSpontaneousAmpPayment( + t, test.keySendEnabled, test.failReconstruction, + test.numShards, + ) + }) + } +} + +// testSpontaneousAmpPayment runs a specific spontaneous AMP test case. +func testSpontaneousAmpPayment( + t *testing.T, keySendEnabled, failReconstruction bool, numShards int) { + + defer timeout()() + + ctx := newTestContext(t) + defer ctx.cleanup() + + ctx.registry.cfg.AcceptKeySend = keySendEnabled + + allSubscriptions, err := ctx.registry.SubscribeNotifications(0, 0) + require.Nil(t, err) + defer allSubscriptions.Cancel() + + const ( + totalAmt = lnwire.MilliSatoshi(360) + expiry = uint32(testCurrentHeight + 20) + ) + + var ( + shardAmt = totalAmt / lnwire.MilliSatoshi(numShards) + payAddr [32]byte + setID [32]byte + ) + _, err = rand.Read(payAddr[:]) + require.NoError(t, err) + _, err = rand.Read(setID[:]) + require.NoError(t, err) + + var sharer amp.Sharer + sharer, err = amp.NewSeedSharer() + require.NoError(t, err) + + // Asserts that a new invoice is published on the NewInvoices channel. + checkOpenSubscription := func() { + t.Helper() + newInvoice := <-allSubscriptions.NewInvoices + require.Equal(t, newInvoice.State, channeldb.ContractOpen) + } + + // Asserts that a settled invoice is published on the SettledInvoices + // channel. + checkSettleSubscription := func() { + t.Helper() + settledInvoice := <-allSubscriptions.SettledInvoices + require.Equal(t, settledInvoice.State, channeldb.ContractSettled) + } + + // Asserts that no invoice is published on the SettledInvoices channel + // w/in two seconds. + checkNoSettleSubscription := func() { + t.Helper() + select { + case <-allSubscriptions.SettledInvoices: + t.Fatal("no settle ntfn expected") + case <-time.After(2 * time.Second): + } + } + + // Record the hodl channels of all HTLCs but the last one, which + // received its resolution directly from NotifyExistHopHtlc. + hodlChans := make(map[lntypes.Preimage]chan interface{}) + for i := 0; i < numShards; i++ { + isFinalShard := i == numShards-1 + + hodlChan := make(chan interface{}, 1) + + var child *amp.Child + if !isFinalShard { + var left amp.Sharer + left, sharer, err = sharer.Split() + require.NoError(t, err) + + child = left.Child(uint32(i)) + + // Only store the first numShards-1 hodlChans. + hodlChans[child.Preimage] = hodlChan + } else { + child = sharer.Child(uint32(i)) + } + + // Send a blank share when the set should fail reconstruction, + // otherwise send the derived share. + var share [32]byte + if !failReconstruction { + share = child.Share + } + + payload := &mockPayload{ + mpp: record.NewMPP(totalAmt, payAddr), + amp: record.NewAMP(share, setID, uint32(i)), + } + + resolution, err := ctx.registry.NotifyExitHopHtlc( + child.Hash, shardAmt, expiry, + testCurrentHeight, getCircuitKey(uint64(i)), hodlChan, + payload, + ) + require.NoError(t, err) + + // When keysend is disabled all HTLC should fail with invoice + // not found, since one is not inserted before executing + // UpdateInvoice. + if !keySendEnabled { + require.NotNil(t, resolution) + checkFailResolution(t, resolution, ResultInvoiceNotFound) + continue + } + + // Check that resolutions are properly formed. + if !isFinalShard { + // Non-final shares should always return a nil + // resolution, theirs will be delivered via the + // hodlChan. + require.Nil(t, resolution) + } else { + // The final share should receive a non-nil resolution. + // Also assert that it is the proper type based on the + // test case. + require.NotNil(t, resolution) + if failReconstruction { + checkFailResolution(t, resolution, ResultAmpReconstruction) + } else { + checkSettleResolution(t, resolution, child.Preimage) + } + } + + // Assert the behavior of the Open and Settle notifications. + // There should always be an open (keysend is enabled) followed + // by settle for valid AMP payments. + // + // NOTE: The cases are split in separate if conditions, rather + // than else-if, to properly handle the case when there is only + // one shard. + if i == 0 { + checkOpenSubscription() + } + if isFinalShard { + if failReconstruction { + checkNoSettleSubscription() + } else { + checkSettleSubscription() + } + } + } + + // No need to check the hodl chans when keysend is not enabled. + if !keySendEnabled { + return + } + + // For the non-final hodl chans, assert that they receive the expected + // failure or preimage. + for preimage, hodlChan := range hodlChans { + resolution, ok := (<-hodlChan).(HtlcResolution) + require.True(t, ok) + require.NotNil(t, resolution) + if failReconstruction { + checkFailResolution(t, resolution, ResultAmpReconstruction) + } else { + checkSettleResolution(t, resolution, preimage) + } + } +} diff --git a/invoices/resolution_result.go b/invoices/resolution_result.go index fc95661f47f..810f20531cb 100644 --- a/invoices/resolution_result.go +++ b/invoices/resolution_result.go @@ -180,6 +180,23 @@ func (f FailResolutionResult) FailureString() string { } } +// IsSetFailure returns true if this failure should result in the entire HTLC +// set being failed with the same result. +func (f FailResolutionResult) IsSetFailure() bool { + switch f { + case + ResultAmpReconstruction, + ResultHtlcSetTotalTooLow, + ResultHtlcSetTotalMismatch, + ResultHtlcSetOverpayment: + + return true + + default: + return false + } +} + // SettleResolutionResult provides metadata which about a htlc that was failed // by the registry. It can be used to take custom actions on resolution of the // htlc. From cfa9e954c7c0026262553d15381a6180214ee383 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:52:38 -0700 Subject: [PATCH 18/22] channeldb/invoice: allow creating AMP invoices w/o preiamge --- channeldb/invoices.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 2dcd1be87da..fbec1a3930e 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -719,7 +719,12 @@ func validateInvoice(i *Invoice, paymentHash lntypes.Hash) error { return err } - if i.Terms.PaymentPreimage == nil && !i.HodlInvoice { + // AMP invoices and hodl invoices are allowed to have no preimage + // specified. + isAMP := i.Terms.Features.HasFeature( + lnwire.AMPOptional, + ) + if i.Terms.PaymentPreimage == nil && !(i.HodlInvoice || isAMP) { return errors.New("non-hodl invoices must have a preimage") } From 00581efec6b9660ee533df5d566c1b5f641fae9e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:52:56 -0700 Subject: [PATCH 19/22] lnrpc: add AMPRecord to Hop --- lnrpc/routerrpc/router.swagger.json | 23 +- lnrpc/rpc.pb.go | 1829 ++++++++++++++------------- lnrpc/rpc.proto | 24 +- lnrpc/rpc.swagger.json | 23 +- 4 files changed, 1016 insertions(+), 883 deletions(-) diff --git a/lnrpc/routerrpc/router.swagger.json b/lnrpc/routerrpc/router.swagger.json index 390e3194dbc..32f0af50397 100644 --- a/lnrpc/routerrpc/router.swagger.json +++ b/lnrpc/routerrpc/router.swagger.json @@ -441,6 +441,23 @@ ], "default": "IN_FLIGHT" }, + "lnrpcAMPRecord": { + "type": "object", + "properties": { + "root_share": { + "type": "string", + "format": "byte" + }, + "set_id": { + "type": "string", + "format": "byte" + }, + "child_index": { + "type": "integer", + "format": "int64" + } + } + }, "lnrpcChannelPoint": { "type": "object", "properties": { @@ -677,7 +694,11 @@ }, "mpp_record": { "$ref": "#/definitions/lnrpcMPPRecord", - "description": "An optional TLV record that signals the use of an MPP payment. If present,\nthe receiver will enforce that that the same mpp_record is included in the\nfinal hop payload of all non-zero payments in the HTLC set. If empty, a\nregular single-shot payment is or was attempted." + "description": "An optional TLV record that signals the use of an MPP payment. If present,\nthe receiver will enforce that the same mpp_record is included in the final\nhop payload of all non-zero payments in the HTLC set. If empty, a regular\nsingle-shot payment is or was attempted." + }, + "amp_record": { + "$ref": "#/definitions/lnrpcAMPRecord", + "description": "An optional TLV record that signals the use of an AMP payment. If present,\nthe receiver will treat all received payments including the same\n(payment_addr, set_id) pair as being part of one logical payment. The\npayment will be settled by XORing the root_share's together and deriving the\nchild hashes and preimages according to BOLT XX. Must be used in conjunction\nwith mpp_record." }, "custom_records": { "type": "object", diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go index 55d176be849..cb13ab99583 100644 --- a/lnrpc/rpc.pb.go +++ b/lnrpc/rpc.pb.go @@ -613,7 +613,7 @@ func (x Invoice_InvoiceState) String() string { } func (Invoice_InvoiceState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{111, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{112, 0} } type Payment_PaymentStatus int32 @@ -644,7 +644,7 @@ func (x Payment_PaymentStatus) String() string { } func (Payment_PaymentStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{119, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{120, 0} } type HTLCAttempt_HTLCStatus int32 @@ -672,7 +672,7 @@ func (x HTLCAttempt_HTLCStatus) String() string { } func (HTLCAttempt_HTLCStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{120, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{121, 0} } type Failure_FailureCode int32 @@ -786,7 +786,7 @@ func (x Failure_FailureCode) String() string { } func (Failure_FailureCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{160, 0} + return fileDescriptor_77a6da22d6a3feb1, []int{161, 0} } type Utxo struct { @@ -7717,11 +7717,19 @@ type Hop struct { TlvPayload bool `protobuf:"varint,9,opt,name=tlv_payload,json=tlvPayload,proto3" json:"tlv_payload,omitempty"` // //An optional TLV record that signals the use of an MPP payment. If present, - //the receiver will enforce that that the same mpp_record is included in the - //final hop payload of all non-zero payments in the HTLC set. If empty, a - //regular single-shot payment is or was attempted. + //the receiver will enforce that the same mpp_record is included in the final + //hop payload of all non-zero payments in the HTLC set. If empty, a regular + //single-shot payment is or was attempted. MppRecord *MPPRecord `protobuf:"bytes,10,opt,name=mpp_record,json=mppRecord,proto3" json:"mpp_record,omitempty"` // + //An optional TLV record that signals the use of an AMP payment. If present, + //the receiver will treat all received payments including the same + //(payment_addr, set_id) pair as being part of one logical payment. The + //payment will be settled by XORing the root_share's together and deriving the + //child hashes and preimages according to BOLT XX. Must be used in conjunction + //with mpp_record. + AmpRecord *AMPRecord `protobuf:"bytes,12,opt,name=amp_record,json=ampRecord,proto3" json:"amp_record,omitempty"` + // //An optional set of key-value TLV records. This is useful within the context //of the SendToRoute call as it allows callers to specify arbitrary K-V pairs //to drop off at each hop within the onion. @@ -7828,6 +7836,13 @@ func (m *Hop) GetMppRecord() *MPPRecord { return nil } +func (m *Hop) GetAmpRecord() *AMPRecord { + if m != nil { + return m.AmpRecord + } + return nil +} + func (m *Hop) GetCustomRecords() map[uint64][]byte { if m != nil { return m.CustomRecords @@ -7892,6 +7907,61 @@ func (m *MPPRecord) GetTotalAmtMsat() int64 { return 0 } +type AMPRecord struct { + RootShare []byte `protobuf:"bytes,1,opt,name=root_share,json=rootShare,proto3" json:"root_share,omitempty"` + SetId []byte `protobuf:"bytes,2,opt,name=set_id,json=setId,proto3" json:"set_id,omitempty"` + ChildIndex uint32 `protobuf:"varint,3,opt,name=child_index,json=childIndex,proto3" json:"child_index,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AMPRecord) Reset() { *m = AMPRecord{} } +func (m *AMPRecord) String() string { return proto.CompactTextString(m) } +func (*AMPRecord) ProtoMessage() {} +func (*AMPRecord) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{87} +} + +func (m *AMPRecord) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_AMPRecord.Unmarshal(m, b) +} +func (m *AMPRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_AMPRecord.Marshal(b, m, deterministic) +} +func (m *AMPRecord) XXX_Merge(src proto.Message) { + xxx_messageInfo_AMPRecord.Merge(m, src) +} +func (m *AMPRecord) XXX_Size() int { + return xxx_messageInfo_AMPRecord.Size(m) +} +func (m *AMPRecord) XXX_DiscardUnknown() { + xxx_messageInfo_AMPRecord.DiscardUnknown(m) +} + +var xxx_messageInfo_AMPRecord proto.InternalMessageInfo + +func (m *AMPRecord) GetRootShare() []byte { + if m != nil { + return m.RootShare + } + return nil +} + +func (m *AMPRecord) GetSetId() []byte { + if m != nil { + return m.SetId + } + return nil +} + +func (m *AMPRecord) GetChildIndex() uint32 { + if m != nil { + return m.ChildIndex + } + return 0 +} + // //A path through the channel graph which runs over one or more channels in //succession. This struct carries all the information required to craft the @@ -7935,7 +8005,7 @@ func (m *Route) Reset() { *m = Route{} } func (m *Route) String() string { return proto.CompactTextString(m) } func (*Route) ProtoMessage() {} func (*Route) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{87} + return fileDescriptor_77a6da22d6a3feb1, []int{88} } func (m *Route) XXX_Unmarshal(b []byte) error { @@ -8014,7 +8084,7 @@ func (m *NodeInfoRequest) Reset() { *m = NodeInfoRequest{} } func (m *NodeInfoRequest) String() string { return proto.CompactTextString(m) } func (*NodeInfoRequest) ProtoMessage() {} func (*NodeInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{88} + return fileDescriptor_77a6da22d6a3feb1, []int{89} } func (m *NodeInfoRequest) XXX_Unmarshal(b []byte) error { @@ -8071,7 +8141,7 @@ func (m *NodeInfo) Reset() { *m = NodeInfo{} } func (m *NodeInfo) String() string { return proto.CompactTextString(m) } func (*NodeInfo) ProtoMessage() {} func (*NodeInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{89} + return fileDescriptor_77a6da22d6a3feb1, []int{90} } func (m *NodeInfo) XXX_Unmarshal(b []byte) error { @@ -8141,7 +8211,7 @@ func (m *LightningNode) Reset() { *m = LightningNode{} } func (m *LightningNode) String() string { return proto.CompactTextString(m) } func (*LightningNode) ProtoMessage() {} func (*LightningNode) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{90} + return fileDescriptor_77a6da22d6a3feb1, []int{91} } func (m *LightningNode) XXX_Unmarshal(b []byte) error { @@ -8216,7 +8286,7 @@ func (m *NodeAddress) Reset() { *m = NodeAddress{} } func (m *NodeAddress) String() string { return proto.CompactTextString(m) } func (*NodeAddress) ProtoMessage() {} func (*NodeAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{91} + return fileDescriptor_77a6da22d6a3feb1, []int{92} } func (m *NodeAddress) XXX_Unmarshal(b []byte) error { @@ -8268,7 +8338,7 @@ func (m *RoutingPolicy) Reset() { *m = RoutingPolicy{} } func (m *RoutingPolicy) String() string { return proto.CompactTextString(m) } func (*RoutingPolicy) ProtoMessage() {} func (*RoutingPolicy) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{92} + return fileDescriptor_77a6da22d6a3feb1, []int{93} } func (m *RoutingPolicy) XXX_Unmarshal(b []byte) error { @@ -8366,7 +8436,7 @@ func (m *ChannelEdge) Reset() { *m = ChannelEdge{} } func (m *ChannelEdge) String() string { return proto.CompactTextString(m) } func (*ChannelEdge) ProtoMessage() {} func (*ChannelEdge) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{93} + return fileDescriptor_77a6da22d6a3feb1, []int{94} } func (m *ChannelEdge) XXX_Unmarshal(b []byte) error { @@ -8459,7 +8529,7 @@ func (m *ChannelGraphRequest) Reset() { *m = ChannelGraphRequest{} } func (m *ChannelGraphRequest) String() string { return proto.CompactTextString(m) } func (*ChannelGraphRequest) ProtoMessage() {} func (*ChannelGraphRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{94} + return fileDescriptor_77a6da22d6a3feb1, []int{95} } func (m *ChannelGraphRequest) XXX_Unmarshal(b []byte) error { @@ -8502,7 +8572,7 @@ func (m *ChannelGraph) Reset() { *m = ChannelGraph{} } func (m *ChannelGraph) String() string { return proto.CompactTextString(m) } func (*ChannelGraph) ProtoMessage() {} func (*ChannelGraph) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{95} + return fileDescriptor_77a6da22d6a3feb1, []int{96} } func (m *ChannelGraph) XXX_Unmarshal(b []byte) error { @@ -8549,7 +8619,7 @@ func (m *NodeMetricsRequest) Reset() { *m = NodeMetricsRequest{} } func (m *NodeMetricsRequest) String() string { return proto.CompactTextString(m) } func (*NodeMetricsRequest) ProtoMessage() {} func (*NodeMetricsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{96} + return fileDescriptor_77a6da22d6a3feb1, []int{97} } func (m *NodeMetricsRequest) XXX_Unmarshal(b []byte) error { @@ -8594,7 +8664,7 @@ func (m *NodeMetricsResponse) Reset() { *m = NodeMetricsResponse{} } func (m *NodeMetricsResponse) String() string { return proto.CompactTextString(m) } func (*NodeMetricsResponse) ProtoMessage() {} func (*NodeMetricsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{97} + return fileDescriptor_77a6da22d6a3feb1, []int{98} } func (m *NodeMetricsResponse) XXX_Unmarshal(b []byte) error { @@ -8636,7 +8706,7 @@ func (m *FloatMetric) Reset() { *m = FloatMetric{} } func (m *FloatMetric) String() string { return proto.CompactTextString(m) } func (*FloatMetric) ProtoMessage() {} func (*FloatMetric) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{98} + return fileDescriptor_77a6da22d6a3feb1, []int{99} } func (m *FloatMetric) XXX_Unmarshal(b []byte) error { @@ -8686,7 +8756,7 @@ func (m *ChanInfoRequest) Reset() { *m = ChanInfoRequest{} } func (m *ChanInfoRequest) String() string { return proto.CompactTextString(m) } func (*ChanInfoRequest) ProtoMessage() {} func (*ChanInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{99} + return fileDescriptor_77a6da22d6a3feb1, []int{100} } func (m *ChanInfoRequest) XXX_Unmarshal(b []byte) error { @@ -8724,7 +8794,7 @@ func (m *NetworkInfoRequest) Reset() { *m = NetworkInfoRequest{} } func (m *NetworkInfoRequest) String() string { return proto.CompactTextString(m) } func (*NetworkInfoRequest) ProtoMessage() {} func (*NetworkInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{100} + return fileDescriptor_77a6da22d6a3feb1, []int{101} } func (m *NetworkInfoRequest) XXX_Unmarshal(b []byte) error { @@ -8767,7 +8837,7 @@ func (m *NetworkInfo) Reset() { *m = NetworkInfo{} } func (m *NetworkInfo) String() string { return proto.CompactTextString(m) } func (*NetworkInfo) ProtoMessage() {} func (*NetworkInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{101} + return fileDescriptor_77a6da22d6a3feb1, []int{102} } func (m *NetworkInfo) XXX_Unmarshal(b []byte) error { @@ -8875,7 +8945,7 @@ func (m *StopRequest) Reset() { *m = StopRequest{} } func (m *StopRequest) String() string { return proto.CompactTextString(m) } func (*StopRequest) ProtoMessage() {} func (*StopRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{102} + return fileDescriptor_77a6da22d6a3feb1, []int{103} } func (m *StopRequest) XXX_Unmarshal(b []byte) error { @@ -8906,7 +8976,7 @@ func (m *StopResponse) Reset() { *m = StopResponse{} } func (m *StopResponse) String() string { return proto.CompactTextString(m) } func (*StopResponse) ProtoMessage() {} func (*StopResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{103} + return fileDescriptor_77a6da22d6a3feb1, []int{104} } func (m *StopResponse) XXX_Unmarshal(b []byte) error { @@ -8937,7 +9007,7 @@ func (m *GraphTopologySubscription) Reset() { *m = GraphTopologySubscrip func (m *GraphTopologySubscription) String() string { return proto.CompactTextString(m) } func (*GraphTopologySubscription) ProtoMessage() {} func (*GraphTopologySubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{104} + return fileDescriptor_77a6da22d6a3feb1, []int{105} } func (m *GraphTopologySubscription) XXX_Unmarshal(b []byte) error { @@ -8971,7 +9041,7 @@ func (m *GraphTopologyUpdate) Reset() { *m = GraphTopologyUpdate{} } func (m *GraphTopologyUpdate) String() string { return proto.CompactTextString(m) } func (*GraphTopologyUpdate) ProtoMessage() {} func (*GraphTopologyUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{105} + return fileDescriptor_77a6da22d6a3feb1, []int{106} } func (m *GraphTopologyUpdate) XXX_Unmarshal(b []byte) error { @@ -9032,7 +9102,7 @@ func (m *NodeUpdate) Reset() { *m = NodeUpdate{} } func (m *NodeUpdate) String() string { return proto.CompactTextString(m) } func (*NodeUpdate) ProtoMessage() {} func (*NodeUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{106} + return fileDescriptor_77a6da22d6a3feb1, []int{107} } func (m *NodeUpdate) XXX_Unmarshal(b []byte) error { @@ -9116,7 +9186,7 @@ func (m *ChannelEdgeUpdate) Reset() { *m = ChannelEdgeUpdate{} } func (m *ChannelEdgeUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelEdgeUpdate) ProtoMessage() {} func (*ChannelEdgeUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{107} + return fileDescriptor_77a6da22d6a3feb1, []int{108} } func (m *ChannelEdgeUpdate) XXX_Unmarshal(b []byte) error { @@ -9197,7 +9267,7 @@ func (m *ClosedChannelUpdate) Reset() { *m = ClosedChannelUpdate{} } func (m *ClosedChannelUpdate) String() string { return proto.CompactTextString(m) } func (*ClosedChannelUpdate) ProtoMessage() {} func (*ClosedChannelUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{108} + return fileDescriptor_77a6da22d6a3feb1, []int{109} } func (m *ClosedChannelUpdate) XXX_Unmarshal(b []byte) error { @@ -9268,7 +9338,7 @@ func (m *HopHint) Reset() { *m = HopHint{} } func (m *HopHint) String() string { return proto.CompactTextString(m) } func (*HopHint) ProtoMessage() {} func (*HopHint) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{109} + return fileDescriptor_77a6da22d6a3feb1, []int{110} } func (m *HopHint) XXX_Unmarshal(b []byte) error { @@ -9338,7 +9408,7 @@ func (m *RouteHint) Reset() { *m = RouteHint{} } func (m *RouteHint) String() string { return proto.CompactTextString(m) } func (*RouteHint) ProtoMessage() {} func (*RouteHint) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{110} + return fileDescriptor_77a6da22d6a3feb1, []int{111} } func (m *RouteHint) XXX_Unmarshal(b []byte) error { @@ -9476,7 +9546,7 @@ func (m *Invoice) Reset() { *m = Invoice{} } func (m *Invoice) String() string { return proto.CompactTextString(m) } func (*Invoice) ProtoMessage() {} func (*Invoice) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{111} + return fileDescriptor_77a6da22d6a3feb1, []int{112} } func (m *Invoice) XXX_Unmarshal(b []byte) error { @@ -9707,7 +9777,7 @@ func (m *InvoiceHTLC) Reset() { *m = InvoiceHTLC{} } func (m *InvoiceHTLC) String() string { return proto.CompactTextString(m) } func (*InvoiceHTLC) ProtoMessage() {} func (*InvoiceHTLC) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{112} + return fileDescriptor_77a6da22d6a3feb1, []int{113} } func (m *InvoiceHTLC) XXX_Unmarshal(b []byte) error { @@ -9830,7 +9900,7 @@ func (m *AMP) Reset() { *m = AMP{} } func (m *AMP) String() string { return proto.CompactTextString(m) } func (*AMP) ProtoMessage() {} func (*AMP) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{113} + return fileDescriptor_77a6da22d6a3feb1, []int{114} } func (m *AMP) XXX_Unmarshal(b []byte) error { @@ -9913,7 +9983,7 @@ func (m *AddInvoiceResponse) Reset() { *m = AddInvoiceResponse{} } func (m *AddInvoiceResponse) String() string { return proto.CompactTextString(m) } func (*AddInvoiceResponse) ProtoMessage() {} func (*AddInvoiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{114} + return fileDescriptor_77a6da22d6a3feb1, []int{115} } func (m *AddInvoiceResponse) XXX_Unmarshal(b []byte) error { @@ -9982,7 +10052,7 @@ func (m *PaymentHash) Reset() { *m = PaymentHash{} } func (m *PaymentHash) String() string { return proto.CompactTextString(m) } func (*PaymentHash) ProtoMessage() {} func (*PaymentHash) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{115} + return fileDescriptor_77a6da22d6a3feb1, []int{116} } func (m *PaymentHash) XXX_Unmarshal(b []byte) error { @@ -10042,7 +10112,7 @@ func (m *ListInvoiceRequest) Reset() { *m = ListInvoiceRequest{} } func (m *ListInvoiceRequest) String() string { return proto.CompactTextString(m) } func (*ListInvoiceRequest) ProtoMessage() {} func (*ListInvoiceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{116} + return fileDescriptor_77a6da22d6a3feb1, []int{117} } func (m *ListInvoiceRequest) XXX_Unmarshal(b []byte) error { @@ -10113,7 +10183,7 @@ func (m *ListInvoiceResponse) Reset() { *m = ListInvoiceResponse{} } func (m *ListInvoiceResponse) String() string { return proto.CompactTextString(m) } func (*ListInvoiceResponse) ProtoMessage() {} func (*ListInvoiceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{117} + return fileDescriptor_77a6da22d6a3feb1, []int{118} } func (m *ListInvoiceResponse) XXX_Unmarshal(b []byte) error { @@ -10177,7 +10247,7 @@ func (m *InvoiceSubscription) Reset() { *m = InvoiceSubscription{} } func (m *InvoiceSubscription) String() string { return proto.CompactTextString(m) } func (*InvoiceSubscription) ProtoMessage() {} func (*InvoiceSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{118} + return fileDescriptor_77a6da22d6a3feb1, []int{119} } func (m *InvoiceSubscription) XXX_Unmarshal(b []byte) error { @@ -10254,7 +10324,7 @@ func (m *Payment) Reset() { *m = Payment{} } func (m *Payment) String() string { return proto.CompactTextString(m) } func (*Payment) ProtoMessage() {} func (*Payment) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{119} + return fileDescriptor_77a6da22d6a3feb1, []int{120} } func (m *Payment) XXX_Unmarshal(b []byte) error { @@ -10409,7 +10479,7 @@ func (m *HTLCAttempt) Reset() { *m = HTLCAttempt{} } func (m *HTLCAttempt) String() string { return proto.CompactTextString(m) } func (*HTLCAttempt) ProtoMessage() {} func (*HTLCAttempt) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{120} + return fileDescriptor_77a6da22d6a3feb1, []int{121} } func (m *HTLCAttempt) XXX_Unmarshal(b []byte) error { @@ -10509,7 +10579,7 @@ func (m *ListPaymentsRequest) Reset() { *m = ListPaymentsRequest{} } func (m *ListPaymentsRequest) String() string { return proto.CompactTextString(m) } func (*ListPaymentsRequest) ProtoMessage() {} func (*ListPaymentsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{121} + return fileDescriptor_77a6da22d6a3feb1, []int{122} } func (m *ListPaymentsRequest) XXX_Unmarshal(b []byte) error { @@ -10578,7 +10648,7 @@ func (m *ListPaymentsResponse) Reset() { *m = ListPaymentsResponse{} } func (m *ListPaymentsResponse) String() string { return proto.CompactTextString(m) } func (*ListPaymentsResponse) ProtoMessage() {} func (*ListPaymentsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{122} + return fileDescriptor_77a6da22d6a3feb1, []int{123} } func (m *ListPaymentsResponse) XXX_Unmarshal(b []byte) error { @@ -10635,7 +10705,7 @@ func (m *DeleteAllPaymentsRequest) Reset() { *m = DeleteAllPaymentsReque func (m *DeleteAllPaymentsRequest) String() string { return proto.CompactTextString(m) } func (*DeleteAllPaymentsRequest) ProtoMessage() {} func (*DeleteAllPaymentsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{123} + return fileDescriptor_77a6da22d6a3feb1, []int{124} } func (m *DeleteAllPaymentsRequest) XXX_Unmarshal(b []byte) error { @@ -10680,7 +10750,7 @@ func (m *DeleteAllPaymentsResponse) Reset() { *m = DeleteAllPaymentsResp func (m *DeleteAllPaymentsResponse) String() string { return proto.CompactTextString(m) } func (*DeleteAllPaymentsResponse) ProtoMessage() {} func (*DeleteAllPaymentsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{124} + return fileDescriptor_77a6da22d6a3feb1, []int{125} } func (m *DeleteAllPaymentsResponse) XXX_Unmarshal(b []byte) error { @@ -10713,7 +10783,7 @@ func (m *AbandonChannelRequest) Reset() { *m = AbandonChannelRequest{} } func (m *AbandonChannelRequest) String() string { return proto.CompactTextString(m) } func (*AbandonChannelRequest) ProtoMessage() {} func (*AbandonChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{125} + return fileDescriptor_77a6da22d6a3feb1, []int{126} } func (m *AbandonChannelRequest) XXX_Unmarshal(b []byte) error { @@ -10758,7 +10828,7 @@ func (m *AbandonChannelResponse) Reset() { *m = AbandonChannelResponse{} func (m *AbandonChannelResponse) String() string { return proto.CompactTextString(m) } func (*AbandonChannelResponse) ProtoMessage() {} func (*AbandonChannelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{126} + return fileDescriptor_77a6da22d6a3feb1, []int{127} } func (m *AbandonChannelResponse) XXX_Unmarshal(b []byte) error { @@ -10791,7 +10861,7 @@ func (m *DebugLevelRequest) Reset() { *m = DebugLevelRequest{} } func (m *DebugLevelRequest) String() string { return proto.CompactTextString(m) } func (*DebugLevelRequest) ProtoMessage() {} func (*DebugLevelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{127} + return fileDescriptor_77a6da22d6a3feb1, []int{128} } func (m *DebugLevelRequest) XXX_Unmarshal(b []byte) error { @@ -10837,7 +10907,7 @@ func (m *DebugLevelResponse) Reset() { *m = DebugLevelResponse{} } func (m *DebugLevelResponse) String() string { return proto.CompactTextString(m) } func (*DebugLevelResponse) ProtoMessage() {} func (*DebugLevelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{128} + return fileDescriptor_77a6da22d6a3feb1, []int{129} } func (m *DebugLevelResponse) XXX_Unmarshal(b []byte) error { @@ -10877,7 +10947,7 @@ func (m *PayReqString) Reset() { *m = PayReqString{} } func (m *PayReqString) String() string { return proto.CompactTextString(m) } func (*PayReqString) ProtoMessage() {} func (*PayReqString) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{129} + return fileDescriptor_77a6da22d6a3feb1, []int{130} } func (m *PayReqString) XXX_Unmarshal(b []byte) error { @@ -10928,7 +10998,7 @@ func (m *PayReq) Reset() { *m = PayReq{} } func (m *PayReq) String() string { return proto.CompactTextString(m) } func (*PayReq) ProtoMessage() {} func (*PayReq) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{130} + return fileDescriptor_77a6da22d6a3feb1, []int{131} } func (m *PayReq) XXX_Unmarshal(b []byte) error { @@ -11053,7 +11123,7 @@ func (m *Feature) Reset() { *m = Feature{} } func (m *Feature) String() string { return proto.CompactTextString(m) } func (*Feature) ProtoMessage() {} func (*Feature) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{131} + return fileDescriptor_77a6da22d6a3feb1, []int{132} } func (m *Feature) XXX_Unmarshal(b []byte) error { @@ -11105,7 +11175,7 @@ func (m *FeeReportRequest) Reset() { *m = FeeReportRequest{} } func (m *FeeReportRequest) String() string { return proto.CompactTextString(m) } func (*FeeReportRequest) ProtoMessage() {} func (*FeeReportRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{132} + return fileDescriptor_77a6da22d6a3feb1, []int{133} } func (m *FeeReportRequest) XXX_Unmarshal(b []byte) error { @@ -11148,7 +11218,7 @@ func (m *ChannelFeeReport) Reset() { *m = ChannelFeeReport{} } func (m *ChannelFeeReport) String() string { return proto.CompactTextString(m) } func (*ChannelFeeReport) ProtoMessage() {} func (*ChannelFeeReport) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{133} + return fileDescriptor_77a6da22d6a3feb1, []int{134} } func (m *ChannelFeeReport) XXX_Unmarshal(b []byte) error { @@ -11226,7 +11296,7 @@ func (m *FeeReportResponse) Reset() { *m = FeeReportResponse{} } func (m *FeeReportResponse) String() string { return proto.CompactTextString(m) } func (*FeeReportResponse) ProtoMessage() {} func (*FeeReportResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{134} + return fileDescriptor_77a6da22d6a3feb1, []int{135} } func (m *FeeReportResponse) XXX_Unmarshal(b []byte) error { @@ -11304,7 +11374,7 @@ func (m *PolicyUpdateRequest) Reset() { *m = PolicyUpdateRequest{} } func (m *PolicyUpdateRequest) String() string { return proto.CompactTextString(m) } func (*PolicyUpdateRequest) ProtoMessage() {} func (*PolicyUpdateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{135} + return fileDescriptor_77a6da22d6a3feb1, []int{136} } func (m *PolicyUpdateRequest) XXX_Unmarshal(b []byte) error { @@ -11422,7 +11492,7 @@ func (m *PolicyUpdateResponse) Reset() { *m = PolicyUpdateResponse{} } func (m *PolicyUpdateResponse) String() string { return proto.CompactTextString(m) } func (*PolicyUpdateResponse) ProtoMessage() {} func (*PolicyUpdateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{136} + return fileDescriptor_77a6da22d6a3feb1, []int{137} } func (m *PolicyUpdateResponse) XXX_Unmarshal(b []byte) error { @@ -11467,7 +11537,7 @@ func (m *ForwardingHistoryRequest) Reset() { *m = ForwardingHistoryReque func (m *ForwardingHistoryRequest) String() string { return proto.CompactTextString(m) } func (*ForwardingHistoryRequest) ProtoMessage() {} func (*ForwardingHistoryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{137} + return fileDescriptor_77a6da22d6a3feb1, []int{138} } func (m *ForwardingHistoryRequest) XXX_Unmarshal(b []byte) error { @@ -11553,7 +11623,7 @@ func (m *ForwardingEvent) Reset() { *m = ForwardingEvent{} } func (m *ForwardingEvent) String() string { return proto.CompactTextString(m) } func (*ForwardingEvent) ProtoMessage() {} func (*ForwardingEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{138} + return fileDescriptor_77a6da22d6a3feb1, []int{139} } func (m *ForwardingEvent) XXX_Unmarshal(b []byte) error { @@ -11661,7 +11731,7 @@ func (m *ForwardingHistoryResponse) Reset() { *m = ForwardingHistoryResp func (m *ForwardingHistoryResponse) String() string { return proto.CompactTextString(m) } func (*ForwardingHistoryResponse) ProtoMessage() {} func (*ForwardingHistoryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{139} + return fileDescriptor_77a6da22d6a3feb1, []int{140} } func (m *ForwardingHistoryResponse) XXX_Unmarshal(b []byte) error { @@ -11708,7 +11778,7 @@ func (m *ExportChannelBackupRequest) Reset() { *m = ExportChannelBackupR func (m *ExportChannelBackupRequest) String() string { return proto.CompactTextString(m) } func (*ExportChannelBackupRequest) ProtoMessage() {} func (*ExportChannelBackupRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{140} + return fileDescriptor_77a6da22d6a3feb1, []int{141} } func (m *ExportChannelBackupRequest) XXX_Unmarshal(b []byte) error { @@ -11755,7 +11825,7 @@ func (m *ChannelBackup) Reset() { *m = ChannelBackup{} } func (m *ChannelBackup) String() string { return proto.CompactTextString(m) } func (*ChannelBackup) ProtoMessage() {} func (*ChannelBackup) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{141} + return fileDescriptor_77a6da22d6a3feb1, []int{142} } func (m *ChannelBackup) XXX_Unmarshal(b []byte) error { @@ -11809,7 +11879,7 @@ func (m *MultiChanBackup) Reset() { *m = MultiChanBackup{} } func (m *MultiChanBackup) String() string { return proto.CompactTextString(m) } func (*MultiChanBackup) ProtoMessage() {} func (*MultiChanBackup) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{142} + return fileDescriptor_77a6da22d6a3feb1, []int{143} } func (m *MultiChanBackup) XXX_Unmarshal(b []byte) error { @@ -11854,7 +11924,7 @@ func (m *ChanBackupExportRequest) Reset() { *m = ChanBackupExportRequest func (m *ChanBackupExportRequest) String() string { return proto.CompactTextString(m) } func (*ChanBackupExportRequest) ProtoMessage() {} func (*ChanBackupExportRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{143} + return fileDescriptor_77a6da22d6a3feb1, []int{144} } func (m *ChanBackupExportRequest) XXX_Unmarshal(b []byte) error { @@ -11893,7 +11963,7 @@ func (m *ChanBackupSnapshot) Reset() { *m = ChanBackupSnapshot{} } func (m *ChanBackupSnapshot) String() string { return proto.CompactTextString(m) } func (*ChanBackupSnapshot) ProtoMessage() {} func (*ChanBackupSnapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{144} + return fileDescriptor_77a6da22d6a3feb1, []int{145} } func (m *ChanBackupSnapshot) XXX_Unmarshal(b []byte) error { @@ -11941,7 +12011,7 @@ func (m *ChannelBackups) Reset() { *m = ChannelBackups{} } func (m *ChannelBackups) String() string { return proto.CompactTextString(m) } func (*ChannelBackups) ProtoMessage() {} func (*ChannelBackups) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{145} + return fileDescriptor_77a6da22d6a3feb1, []int{146} } func (m *ChannelBackups) XXX_Unmarshal(b []byte) error { @@ -11983,7 +12053,7 @@ func (m *RestoreChanBackupRequest) Reset() { *m = RestoreChanBackupReque func (m *RestoreChanBackupRequest) String() string { return proto.CompactTextString(m) } func (*RestoreChanBackupRequest) ProtoMessage() {} func (*RestoreChanBackupRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{146} + return fileDescriptor_77a6da22d6a3feb1, []int{147} } func (m *RestoreChanBackupRequest) XXX_Unmarshal(b []byte) error { @@ -12059,7 +12129,7 @@ func (m *RestoreBackupResponse) Reset() { *m = RestoreBackupResponse{} } func (m *RestoreBackupResponse) String() string { return proto.CompactTextString(m) } func (*RestoreBackupResponse) ProtoMessage() {} func (*RestoreBackupResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{147} + return fileDescriptor_77a6da22d6a3feb1, []int{148} } func (m *RestoreBackupResponse) XXX_Unmarshal(b []byte) error { @@ -12090,7 +12160,7 @@ func (m *ChannelBackupSubscription) Reset() { *m = ChannelBackupSubscrip func (m *ChannelBackupSubscription) String() string { return proto.CompactTextString(m) } func (*ChannelBackupSubscription) ProtoMessage() {} func (*ChannelBackupSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{148} + return fileDescriptor_77a6da22d6a3feb1, []int{149} } func (m *ChannelBackupSubscription) XXX_Unmarshal(b []byte) error { @@ -12121,7 +12191,7 @@ func (m *VerifyChanBackupResponse) Reset() { *m = VerifyChanBackupRespon func (m *VerifyChanBackupResponse) String() string { return proto.CompactTextString(m) } func (*VerifyChanBackupResponse) ProtoMessage() {} func (*VerifyChanBackupResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{149} + return fileDescriptor_77a6da22d6a3feb1, []int{150} } func (m *VerifyChanBackupResponse) XXX_Unmarshal(b []byte) error { @@ -12156,7 +12226,7 @@ func (m *MacaroonPermission) Reset() { *m = MacaroonPermission{} } func (m *MacaroonPermission) String() string { return proto.CompactTextString(m) } func (*MacaroonPermission) ProtoMessage() {} func (*MacaroonPermission) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{150} + return fileDescriptor_77a6da22d6a3feb1, []int{151} } func (m *MacaroonPermission) XXX_Unmarshal(b []byte) error { @@ -12205,7 +12275,7 @@ func (m *BakeMacaroonRequest) Reset() { *m = BakeMacaroonRequest{} } func (m *BakeMacaroonRequest) String() string { return proto.CompactTextString(m) } func (*BakeMacaroonRequest) ProtoMessage() {} func (*BakeMacaroonRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{151} + return fileDescriptor_77a6da22d6a3feb1, []int{152} } func (m *BakeMacaroonRequest) XXX_Unmarshal(b []byte) error { @@ -12252,7 +12322,7 @@ func (m *BakeMacaroonResponse) Reset() { *m = BakeMacaroonResponse{} } func (m *BakeMacaroonResponse) String() string { return proto.CompactTextString(m) } func (*BakeMacaroonResponse) ProtoMessage() {} func (*BakeMacaroonResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{152} + return fileDescriptor_77a6da22d6a3feb1, []int{153} } func (m *BakeMacaroonResponse) XXX_Unmarshal(b []byte) error { @@ -12290,7 +12360,7 @@ func (m *ListMacaroonIDsRequest) Reset() { *m = ListMacaroonIDsRequest{} func (m *ListMacaroonIDsRequest) String() string { return proto.CompactTextString(m) } func (*ListMacaroonIDsRequest) ProtoMessage() {} func (*ListMacaroonIDsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{153} + return fileDescriptor_77a6da22d6a3feb1, []int{154} } func (m *ListMacaroonIDsRequest) XXX_Unmarshal(b []byte) error { @@ -12323,7 +12393,7 @@ func (m *ListMacaroonIDsResponse) Reset() { *m = ListMacaroonIDsResponse func (m *ListMacaroonIDsResponse) String() string { return proto.CompactTextString(m) } func (*ListMacaroonIDsResponse) ProtoMessage() {} func (*ListMacaroonIDsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{154} + return fileDescriptor_77a6da22d6a3feb1, []int{155} } func (m *ListMacaroonIDsResponse) XXX_Unmarshal(b []byte) error { @@ -12363,7 +12433,7 @@ func (m *DeleteMacaroonIDRequest) Reset() { *m = DeleteMacaroonIDRequest func (m *DeleteMacaroonIDRequest) String() string { return proto.CompactTextString(m) } func (*DeleteMacaroonIDRequest) ProtoMessage() {} func (*DeleteMacaroonIDRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{155} + return fileDescriptor_77a6da22d6a3feb1, []int{156} } func (m *DeleteMacaroonIDRequest) XXX_Unmarshal(b []byte) error { @@ -12403,7 +12473,7 @@ func (m *DeleteMacaroonIDResponse) Reset() { *m = DeleteMacaroonIDRespon func (m *DeleteMacaroonIDResponse) String() string { return proto.CompactTextString(m) } func (*DeleteMacaroonIDResponse) ProtoMessage() {} func (*DeleteMacaroonIDResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{156} + return fileDescriptor_77a6da22d6a3feb1, []int{157} } func (m *DeleteMacaroonIDResponse) XXX_Unmarshal(b []byte) error { @@ -12443,7 +12513,7 @@ func (m *MacaroonPermissionList) Reset() { *m = MacaroonPermissionList{} func (m *MacaroonPermissionList) String() string { return proto.CompactTextString(m) } func (*MacaroonPermissionList) ProtoMessage() {} func (*MacaroonPermissionList) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{157} + return fileDescriptor_77a6da22d6a3feb1, []int{158} } func (m *MacaroonPermissionList) XXX_Unmarshal(b []byte) error { @@ -12481,7 +12551,7 @@ func (m *ListPermissionsRequest) Reset() { *m = ListPermissionsRequest{} func (m *ListPermissionsRequest) String() string { return proto.CompactTextString(m) } func (*ListPermissionsRequest) ProtoMessage() {} func (*ListPermissionsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{158} + return fileDescriptor_77a6da22d6a3feb1, []int{159} } func (m *ListPermissionsRequest) XXX_Unmarshal(b []byte) error { @@ -12516,7 +12586,7 @@ func (m *ListPermissionsResponse) Reset() { *m = ListPermissionsResponse func (m *ListPermissionsResponse) String() string { return proto.CompactTextString(m) } func (*ListPermissionsResponse) ProtoMessage() {} func (*ListPermissionsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{159} + return fileDescriptor_77a6da22d6a3feb1, []int{160} } func (m *ListPermissionsResponse) XXX_Unmarshal(b []byte) error { @@ -12572,7 +12642,7 @@ func (m *Failure) Reset() { *m = Failure{} } func (m *Failure) String() string { return proto.CompactTextString(m) } func (*Failure) ProtoMessage() {} func (*Failure) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{160} + return fileDescriptor_77a6da22d6a3feb1, []int{161} } func (m *Failure) XXX_Unmarshal(b []byte) error { @@ -12716,7 +12786,7 @@ func (m *ChannelUpdate) Reset() { *m = ChannelUpdate{} } func (m *ChannelUpdate) String() string { return proto.CompactTextString(m) } func (*ChannelUpdate) ProtoMessage() {} func (*ChannelUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{161} + return fileDescriptor_77a6da22d6a3feb1, []int{162} } func (m *ChannelUpdate) XXX_Unmarshal(b []byte) error { @@ -12834,7 +12904,7 @@ func (m *MacaroonId) Reset() { *m = MacaroonId{} } func (m *MacaroonId) String() string { return proto.CompactTextString(m) } func (*MacaroonId) ProtoMessage() {} func (*MacaroonId) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{162} + return fileDescriptor_77a6da22d6a3feb1, []int{163} } func (m *MacaroonId) XXX_Unmarshal(b []byte) error { @@ -12888,7 +12958,7 @@ func (m *Op) Reset() { *m = Op{} } func (m *Op) String() string { return proto.CompactTextString(m) } func (*Op) ProtoMessage() {} func (*Op) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{163} + return fileDescriptor_77a6da22d6a3feb1, []int{164} } func (m *Op) XXX_Unmarshal(b []byte) error { @@ -13043,6 +13113,7 @@ func init() { proto.RegisterType((*Hop)(nil), "lnrpc.Hop") proto.RegisterMapType((map[uint64][]byte)(nil), "lnrpc.Hop.CustomRecordsEntry") proto.RegisterType((*MPPRecord)(nil), "lnrpc.MPPRecord") + proto.RegisterType((*AMPRecord)(nil), "lnrpc.AMPRecord") proto.RegisterType((*Route)(nil), "lnrpc.Route") proto.RegisterType((*NodeInfoRequest)(nil), "lnrpc.NodeInfoRequest") proto.RegisterType((*NodeInfo)(nil), "lnrpc.NodeInfo") @@ -13132,800 +13203,802 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 12685 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, 0x8e, 0xa6, 0xa7, 0x67, 0x7a, 0x2e, 0x3b, 0xbf, 0xd7, 0x4b, 0x49, - 0x54, 0x8b, 0xdb, 0x12, 0xa9, 0x2d, 0x52, 0x3d, 0x6e, 0xc3, 0x76, 0xb9, 0x44, 0x1e, 0x49, 0xf5, - 0x37, 0x59, 0xc5, 0xad, 0x2a, 0xaa, 0xa5, 0x0d, 0x02, 0xf8, 0xc1, 0xb1, 0x03, 0xc3, 0x08, 0x10, - 0x20, 0x0e, 0x10, 0x24, 0x46, 0x12, 0x24, 0x48, 0xde, 0x0c, 0x03, 0xb6, 0x9f, 0x92, 0x87, 0x3c, - 0x25, 0x08, 0x90, 0x20, 0x08, 0x10, 0x23, 0x17, 0x04, 0x09, 0x02, 0x24, 0x0e, 0x10, 0x03, 0x89, - 0x01, 0x3f, 0x26, 0x41, 0x82, 0xf3, 0x9d, 0x4b, 0x9d, 0xba, 0xa8, 0xbb, 0x67, 0x3d, 0xd9, 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, 0x47, 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, 0x73, 0x2b, 0x18, 0xf9, 0xce, 0x2c, - 0x6c, 0x15, 0x31, 0x6b, 0x65, 0xf6, 0x7c, 0x80, 0xdf, 0xe4, 0x7d, 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, 0x07, 0x1a, 0x23, 0xcf, 0x3d, 0x75, 0xfc, 0xa9, 0x1d, 0x3a, 0x9e, - 0x1b, 0xb4, 0x16, 0xb0, 0xae, 0x38, 0xd0, 0xf8, 0xc7, 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, - 0xf7, 0x61, 0xd9, 0x9d, 0x4f, 0xad, 0x78, 0x55, 0xac, 0x5b, 0x25, 0xb3, 0xe9, 0xce, 0xa7, 0x3b, - 0x3a, 0x9c, 0x75, 0xfe, 0x64, 0xe2, 0x8d, 0x9e, 0xf3, 0x0a, 0x78, 0xf7, 0xaa, 0x08, 0xc1, 0x3a, - 0xde, 0x82, 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, 0x06, 0x80, 0x6f, 0xbf, 0xb0, 0xd8, 0x40, 0xd0, 0xcb, - 0x56, 0x95, 0xcf, 0x82, 0x6f, 0xbf, 0x18, 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, 0xd1, 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, 0x53, 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, 0x6f, 0x25, 0xa8, 0x0d, 0xa8, 0x3b, 0x96, 0x63, 0x44, 0xa0, 0xc8, 0xa6, 0x00, - 0x2b, 0xab, 0x9b, 0xf8, 0x9b, 0xbc, 0x0d, 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, 0xb7, 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, - 0x0f, 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, 0x7c, 0x07, 0xaa, 0xa7, 0x94, - 0x5a, 0x38, 0x58, 0xad, 0x4a, 0x6c, 0xab, 0xcb, 0x19, 0x32, 0x2b, 0xa7, 0x72, 0xae, 0xbe, 0x03, - 0x4d, 0x6f, 0x1e, 0x9e, 0x79, 0x8e, 0x7b, 0x66, 0x8d, 0xce, 0x6d, 0xd7, 0x72, 0xc6, 0xb8, 0x6a, - 0x8b, 0xdb, 0xf9, 0x07, 0x39, 0x73, 0x51, 0xa6, 0xed, 0x9c, 0xdb, 0x6e, 0x77, 0x4c, 0xde, 0x85, - 0xa5, 0x89, 0x1d, 0x84, 0xd6, 0xb9, 0x37, 0xb3, 0x66, 0xf3, 0x93, 0xe7, 0xf4, 0xaa, 0xd5, 0xc0, - 0x81, 0x68, 0x30, 0xf0, 0xbe, 0x37, 0x3b, 0x42, 0x20, 0x5b, 0x94, 0xd8, 0x4e, 0xde, 0x08, 0xb6, - 0xd8, 0x1b, 0x66, 0x95, 0x41, 0x78, 0xa5, 0xcf, 0x60, 0x05, 0xa7, 0x67, 0x34, 0x0f, 0x42, 0x6f, - 0x6a, 0xf9, 0x74, 0xe4, 0xf9, 0xe3, 0xa0, 0x55, 0xc3, 0xb5, 0xf6, 0x6d, 0xd1, 0x58, 0x6d, 0x8e, - 0xb7, 0x76, 0x69, 0x10, 0xee, 0x20, 0xb2, 0xc9, 0x71, 0x3b, 0x6e, 0xe8, 0x5f, 0x99, 0xcb, 0xe3, - 0x24, 0x9c, 0x7c, 0x07, 0x88, 0x3d, 0x99, 0x78, 0x2f, 0xac, 0x80, 0x4e, 0x4e, 0x2d, 0x31, 0x88, - 0xad, 0xc5, 0xbb, 0xb9, 0x7b, 0x15, 0xb3, 0x89, 0x29, 0x03, 0x3a, 0x39, 0x3d, 0xe2, 0x70, 0xf2, - 0x29, 0xe0, 0xf6, 0xb5, 0x4e, 0xa9, 0x1d, 0xce, 0x7d, 0x1a, 0xb4, 0x96, 0xee, 0x16, 0xee, 0x2d, - 0x3e, 0x5c, 0x56, 0xe3, 0x85, 0xe0, 0x6d, 0x27, 0x34, 0xeb, 0x0c, 0x4f, 0x7c, 0x07, 0xfa, 0x6a, - 0x60, 0xf4, 0xa0, 0xd5, 0x8c, 0xad, 0x06, 0x46, 0x0d, 0x36, 0x77, 0x61, 0x3d, 0xbb, 0xd5, 0x6c, - 0xdd, 0xb1, 0x81, 0x63, 0xeb, 0xb5, 0x68, 0xb2, 0x9f, 0x8c, 0x2c, 0x5c, 0xd8, 0x93, 0x39, 0xc5, - 0x85, 0x5a, 0x37, 0xf9, 0xc7, 0x77, 0xf3, 0x9f, 0xe7, 0x8c, 0xdf, 0xcf, 0x41, 0x9d, 0x0f, 0x44, - 0x30, 0xf3, 0xdc, 0x80, 0x92, 0xb7, 0xa1, 0x21, 0x6b, 0xa6, 0xbe, 0xef, 0xf9, 0x82, 0xd4, 0xca, - 0xe6, 0x74, 0x18, 0x8c, 0x7c, 0x1b, 0x9a, 0x12, 0x69, 0xe6, 0x53, 0x67, 0x6a, 0x9f, 0xc9, 0xa2, - 0xe5, 0x6a, 0x3b, 0x12, 0x60, 0xf2, 0x51, 0x54, 0x9e, 0xef, 0xcd, 0x43, 0x8a, 0xdb, 0xa1, 0xf6, - 0xb0, 0x2e, 0x46, 0xc0, 0x64, 0x30, 0x55, 0x3a, 0x7e, 0xbd, 0xc6, 0x56, 0x30, 0x7e, 0x2b, 0x07, - 0x84, 0x35, 0x7b, 0xe8, 0xf1, 0x02, 0x22, 0x72, 0x16, 0xcb, 0x99, 0x7b, 0xed, 0x4d, 0x94, 0x7f, - 0xd9, 0x26, 0x32, 0xa0, 0xc4, 0xdb, 0x5e, 0xcc, 0x68, 0x3b, 0x4f, 0xfa, 0x41, 0xb1, 0x52, 0x68, - 0x16, 0x8d, 0x7f, 0x57, 0x80, 0x55, 0xb6, 0x94, 0x5d, 0x3a, 0x69, 0x8f, 0x46, 0x74, 0xa6, 0xb6, - 0xd7, 0x1d, 0xa8, 0xb9, 0xde, 0x98, 0xca, 0x45, 0xcd, 0x1b, 0x06, 0x0c, 0xa4, 0xad, 0xe8, 0x73, - 0xdb, 0x71, 0x79, 0xc3, 0xf9, 0x60, 0x56, 0x11, 0x82, 0xcd, 0x7e, 0x17, 0x96, 0x66, 0xd4, 0x1d, - 0xeb, 0xbb, 0xa8, 0xc0, 0x37, 0x86, 0x00, 0x8b, 0x0d, 0x74, 0x07, 0x6a, 0xa7, 0x73, 0x8e, 0xc7, - 0x68, 0x4f, 0x11, 0xd7, 0x00, 0x08, 0x50, 0x9b, 0x93, 0xa0, 0xd9, 0x3c, 0x38, 0xc7, 0xd4, 0x12, - 0xa6, 0x96, 0xd9, 0x37, 0x4b, 0xba, 0x0d, 0x30, 0x9e, 0x07, 0xa1, 0xd8, 0x54, 0x0b, 0x98, 0x58, - 0x65, 0x10, 0xbe, 0xa9, 0x3e, 0x80, 0x95, 0xa9, 0x7d, 0x69, 0xe1, 0xda, 0xb1, 0x1c, 0xd7, 0x3a, - 0x9d, 0xe0, 0x89, 0x50, 0x46, 0xbc, 0xe6, 0xd4, 0xbe, 0x7c, 0xca, 0x52, 0xba, 0xee, 0x1e, 0xc2, - 0x19, 0xe5, 0x19, 0xf1, 0x91, 0xb0, 0x7c, 0x1a, 0x50, 0xff, 0x82, 0x22, 0xb1, 0x28, 0x9a, 0x8b, - 0x02, 0x6c, 0x72, 0x28, 0x6b, 0xd1, 0x94, 0xf5, 0x3b, 0x9c, 0x8c, 0x38, 0x65, 0x30, 0xcb, 0x53, - 0xc7, 0xdd, 0x0f, 0x27, 0x23, 0x76, 0xd8, 0x31, 0x52, 0x33, 0xa3, 0xbe, 0xf5, 0xfc, 0x05, 0x6e, - 0xf3, 0x22, 0x92, 0x96, 0x23, 0xea, 0x3f, 0x79, 0xc1, 0xf8, 0x91, 0x51, 0x80, 0xb4, 0xca, 0xbe, - 0x6a, 0xd5, 0x90, 0x06, 0x54, 0x46, 0x01, 0xa3, 0x52, 0xf6, 0x15, 0xdb, 0xa7, 0xac, 0xb5, 0x36, - 0xce, 0x02, 0x1d, 0x63, 0xf1, 0x01, 0x12, 0xdd, 0x06, 0x36, 0xb6, 0x2d, 0x12, 0x58, 0x3d, 0x01, - 0x5b, 0xf5, 0xb2, 0xb1, 0xa7, 0x13, 0xfb, 0x2c, 0x40, 0xaa, 0xd3, 0x30, 0xeb, 0x02, 0xb8, 0xc7, - 0x60, 0xc6, 0x9f, 0xe6, 0x61, 0x2d, 0x31, 0xb9, 0x62, 0xd3, 0x30, 0x06, 0x04, 0x21, 0x38, 0xb1, - 0x15, 0x53, 0x7c, 0x65, 0xcd, 0x5a, 0x3e, 0x6b, 0xd6, 0x56, 0xa1, 0xc4, 0x37, 0x1b, 0x3f, 0x42, - 0xf9, 0x07, 0xdb, 0x65, 0xf3, 0xd9, 0xa9, 0xef, 0x31, 0x7e, 0xec, 0x7c, 0x1e, 0x8e, 0xbd, 0x17, - 0xae, 0xe0, 0x4b, 0x96, 0x04, 0x7c, 0x20, 0xc0, 0xf1, 0xa1, 0x28, 0x25, 0x86, 0xe2, 0x0e, 0xd4, - 0xc4, 0x0c, 0x20, 0x5f, 0xc7, 0x27, 0x16, 0x04, 0x88, 0x31, 0x76, 0xef, 0x03, 0x51, 0xf3, 0x69, - 0xb1, 0x51, 0xc3, 0x03, 0x8a, 0x4f, 0xec, 0x92, 0x23, 0x26, 0xf4, 0xd0, 0xbe, 0xc4, 0x83, 0xea, - 0x1d, 0x58, 0x64, 0x28, 0x6c, 0x3c, 0x2d, 0x7e, 0xee, 0x57, 0xf8, 0x58, 0x4d, 0xed, 0x4b, 0x36, - 0x98, 0x3b, 0xc8, 0x7a, 0xbd, 0x09, 0x35, 0x39, 0xa9, 0x96, 0xe3, 0x8a, 0x79, 0xad, 0x8a, 0x79, - 0xed, 0xba, 0xec, 0xb8, 0x61, 0xe9, 0x7c, 0x9c, 0xac, 0x31, 0x9d, 0x85, 0xe7, 0x82, 0x8c, 0x2f, - 0x4e, 0x1d, 0x97, 0x0f, 0xef, 0x2e, 0x83, 0x1a, 0xbf, 0x9d, 0x83, 0xba, 0x18, 0x75, 0x64, 0x23, - 0xc9, 0x16, 0x10, 0xb9, 0xc4, 0xc3, 0x4b, 0x67, 0x6c, 0x9d, 0x5c, 0x85, 0x34, 0xe0, 0x3b, 0x6a, - 0xff, 0x86, 0xd9, 0x14, 0x69, 0xc3, 0x4b, 0x67, 0xbc, 0xcd, 0x52, 0xc8, 0x7d, 0x68, 0xc6, 0xf0, - 0x83, 0xd0, 0xe7, 0xdb, 0x7d, 0xff, 0x86, 0xb9, 0xa8, 0x61, 0x0f, 0x42, 0x9f, 0x11, 0x10, 0xc6, - 0xa4, 0xce, 0x43, 0xcb, 0x71, 0xc7, 0xf4, 0x12, 0xe7, 0xa3, 0x61, 0xd6, 0x38, 0xac, 0xcb, 0x40, - 0xdb, 0x8b, 0x50, 0xd7, 0x8b, 0x33, 0xce, 0xa0, 0x22, 0x39, 0x5c, 0x64, 0xf1, 0x12, 0x4d, 0x32, - 0xab, 0xa1, 0x6a, 0xc9, 0x4d, 0xa8, 0xc4, 0x5b, 0x60, 0x96, 0xc3, 0xd7, 0xae, 0xd8, 0xf8, 0x1e, - 0x34, 0x0f, 0xd8, 0x44, 0xb8, 0x6c, 0x27, 0x0b, 0x8e, 0x7d, 0x1d, 0x16, 0x34, 0x8a, 0x52, 0x35, - 0xc5, 0x17, 0xe3, 0x59, 0xce, 0xbd, 0x20, 0x14, 0xb5, 0xe0, 0x6f, 0xe3, 0x9f, 0xe4, 0x80, 0x74, - 0x82, 0xd0, 0x99, 0xda, 0x21, 0xdd, 0xa3, 0x8a, 0x66, 0xf6, 0xa1, 0xce, 0x4a, 0x1b, 0x7a, 0x6d, - 0xce, 0x42, 0x73, 0x86, 0xec, 0x7d, 0x41, 0xe3, 0xd2, 0x19, 0xb6, 0x74, 0x6c, 0x7e, 0x4c, 0xc6, - 0x0a, 0x60, 0xcb, 0x2d, 0xb4, 0xfd, 0x33, 0x1a, 0x22, 0xe3, 0x2d, 0x38, 0x46, 0xe0, 0x20, 0xc6, - 0x72, 0x6f, 0xfe, 0x2c, 0x2c, 0xa7, 0xca, 0xd0, 0x0f, 0xad, 0x6a, 0xc6, 0xa1, 0x55, 0xd0, 0x0f, - 0xad, 0x5f, 0xcf, 0xc1, 0x4a, 0xac, 0x61, 0x62, 0x1b, 0x6e, 0x40, 0x99, 0x91, 0x0b, 0xb6, 0x78, - 0x73, 0x5c, 0x10, 0x38, 0xa5, 0xb8, 0xc0, 0x3f, 0x86, 0xd5, 0x53, 0x4a, 0x7d, 0x3b, 0xc4, 0x44, - 0xa4, 0x27, 0x6c, 0x8a, 0x78, 0xc9, 0x9c, 0xea, 0x8b, 0xf4, 0x81, 0x1d, 0x1e, 0x51, 0x9f, 0x4d, - 0x17, 0x31, 0xa0, 0x21, 0x91, 0x2f, 0x10, 0xbb, 0x80, 0x8b, 0xb8, 0x16, 0x20, 0xca, 0x53, 0x06, - 0x32, 0xfe, 0x38, 0x0f, 0x4b, 0xec, 0x1c, 0x3a, 0xb4, 0xdd, 0x2b, 0x39, 0xa0, 0x07, 0x99, 0x03, - 0x7a, 0x4f, 0xe3, 0x3a, 0x34, 0xec, 0xaf, 0x3b, 0x9a, 0x85, 0xe4, 0x68, 0xa6, 0x9b, 0x59, 0x4c, - 0x35, 0x93, 0xbc, 0x03, 0xf5, 0x58, 0xbf, 0x4b, 0xaa, 0xdf, 0x10, 0x44, 0x1d, 0x56, 0xc2, 0xc3, - 0x82, 0x26, 0x3c, 0x30, 0xd2, 0xc2, 0x76, 0x2a, 0xab, 0x3d, 0x10, 0x1c, 0x21, 0xa3, 0xd7, 0xac, - 0xee, 0x80, 0x49, 0x58, 0x01, 0x23, 0x65, 0xd6, 0xdc, 0x15, 0x52, 0x16, 0x1d, 0x23, 0x3d, 0xa8, - 0x98, 0x4d, 0x4c, 0x38, 0x8e, 0xe0, 0x7f, 0xf6, 0x79, 0x7f, 0x17, 0x9a, 0xd1, 0xf0, 0x89, 0x39, - 0x27, 0x50, 0x64, 0x7b, 0x48, 0x14, 0x80, 0xbf, 0x8d, 0xbf, 0x9b, 0xe7, 0x88, 0x3b, 0x9e, 0x13, - 0x89, 0x3a, 0x04, 0x8a, 0xc8, 0x4a, 0x09, 0x44, 0xf6, 0xfb, 0x5a, 0xc1, 0xf1, 0xa7, 0x38, 0xe8, - 0x37, 0xa1, 0x12, 0xb0, 0x01, 0xb4, 0x27, 0x7c, 0xdc, 0x2b, 0x66, 0x99, 0x7d, 0xb7, 0x27, 0x93, - 0x68, 0x3e, 0xca, 0xd7, 0xce, 0x47, 0xe5, 0x75, 0xe6, 0xa3, 0x9a, 0x3d, 0x1f, 0xc6, 0x7b, 0xb0, - 0xac, 0x8d, 0xd2, 0x4b, 0xc6, 0xf3, 0x1c, 0xc8, 0x81, 0x13, 0x84, 0xc7, 0x2e, 0x2b, 0x42, 0xb1, - 0x34, 0xb1, 0x86, 0xe4, 0x12, 0x0d, 0x61, 0x89, 0xf6, 0xa5, 0x48, 0xcc, 0x8b, 0x44, 0xfb, 0x92, - 0x27, 0x5e, 0x2f, 0x33, 0x7e, 0x0e, 0x2b, 0xb1, 0x9a, 0x44, 0xa3, 0xde, 0x82, 0xd2, 0x3c, 0xbc, - 0xf4, 0xa4, 0xb4, 0x58, 0x13, 0x7b, 0xe9, 0x38, 0xbc, 0xf4, 0x4c, 0x9e, 0x62, 0x1c, 0xc3, 0x72, - 0x8f, 0xbe, 0x10, 0x74, 0x51, 0x36, 0xf1, 0x5d, 0x28, 0xbe, 0x42, 0x33, 0x82, 0xe9, 0x7a, 0x83, - 0xf2, 0xf1, 0x06, 0x6d, 0x01, 0xd1, 0x8b, 0x15, 0xed, 0xd1, 0x54, 0x28, 0xb9, 0x98, 0x0a, 0xc5, - 0x78, 0x17, 0xc8, 0xc0, 0x39, 0x73, 0x0f, 0x69, 0x10, 0xd8, 0x67, 0x8a, 0xc6, 0x36, 0xa1, 0x30, - 0x0d, 0xce, 0xc4, 0x81, 0xc0, 0x7e, 0x1a, 0x1f, 0xc3, 0x4a, 0x0c, 0x4f, 0x14, 0xfc, 0x06, 0x54, - 0x03, 0xe7, 0xcc, 0x45, 0x29, 0x40, 0x14, 0x1d, 0x01, 0x8c, 0x3d, 0x58, 0x7d, 0x4a, 0x7d, 0xe7, - 0xf4, 0xea, 0x55, 0xc5, 0xc7, 0xcb, 0xc9, 0x27, 0xcb, 0xe9, 0xc0, 0x5a, 0xa2, 0x1c, 0x51, 0x3d, - 0xdf, 0x7a, 0x62, 0xf6, 0x2b, 0x26, 0xff, 0xd0, 0x0e, 0x99, 0xbc, 0x7e, 0xc8, 0x18, 0x1e, 0x90, - 0x1d, 0xcf, 0x75, 0xe9, 0x28, 0x3c, 0xa2, 0xd4, 0x97, 0x8d, 0x79, 0x5f, 0xdb, 0x67, 0xb5, 0x87, - 0x1b, 0x62, 0xcc, 0x93, 0x27, 0x97, 0xd8, 0x80, 0x04, 0x8a, 0x33, 0xea, 0x4f, 0xb1, 0xe0, 0x8a, - 0x89, 0xbf, 0xd9, 0xe0, 0x86, 0xce, 0x94, 0x7a, 0xf3, 0x50, 0x50, 0x5c, 0xf9, 0x69, 0xac, 0xc1, - 0x4a, 0xac, 0x42, 0xde, 0x6a, 0xe3, 0x01, 0xac, 0xed, 0x3a, 0xc1, 0x28, 0xdd, 0x94, 0x0d, 0x28, - 0xcf, 0xe6, 0x27, 0x56, 0xfc, 0x78, 0x7c, 0x42, 0xaf, 0x8c, 0x16, 0xac, 0x27, 0x73, 0x88, 0xb2, - 0x7e, 0x2d, 0x0f, 0xc5, 0xfd, 0xe1, 0xc1, 0x0e, 0xd9, 0x84, 0x8a, 0xe3, 0x8e, 0xbc, 0x29, 0x13, - 0x0e, 0xf8, 0x68, 0xa8, 0xef, 0x6b, 0xc9, 0xc6, 0x2d, 0xa8, 0xa2, 0x4c, 0x31, 0xf1, 0x46, 0xcf, - 0x05, 0x7b, 0x5e, 0x61, 0x80, 0x03, 0x6f, 0xf4, 0x9c, 0x6d, 0x4d, 0x7a, 0x39, 0x73, 0x7c, 0x54, - 0x37, 0x49, 0x75, 0x4a, 0x91, 0xf3, 0xa3, 0x51, 0x42, 0xa4, 0x74, 0x11, 0xac, 0x13, 0x63, 0x06, - 0x38, 0x9f, 0x5e, 0x3d, 0x47, 0xd6, 0x69, 0x4c, 0x2f, 0xc9, 0x07, 0x40, 0x4e, 0x3d, 0xff, 0x85, - 0xed, 0x2b, 0xd6, 0xd2, 0x15, 0x64, 0xbb, 0x68, 0x2e, 0x47, 0x29, 0x82, 0x6d, 0x22, 0x0f, 0x61, - 0x4d, 0x43, 0xd7, 0x0a, 0xe6, 0x2c, 0xde, 0x4a, 0x94, 0xb8, 0x2f, 0xab, 0x30, 0x7e, 0x35, 0x0f, - 0x44, 0xe4, 0xdf, 0xf1, 0xdc, 0x20, 0xf4, 0x6d, 0xc7, 0x0d, 0x83, 0x38, 0xa3, 0x99, 0x4b, 0x30, - 0x9a, 0xf7, 0xa0, 0x89, 0x6c, 0xae, 0xce, 0x6d, 0xe6, 0x23, 0x9e, 0xdf, 0x8c, 0x38, 0xce, 0x77, - 0x60, 0x31, 0x12, 0x35, 0x94, 0xb6, 0xb1, 0x68, 0xd6, 0x95, 0xb8, 0xc1, 0xb0, 0x3e, 0x84, 0x55, - 0x46, 0x44, 0x24, 0x0b, 0xad, 0x54, 0x27, 0x9c, 0xd8, 0x2e, 0x4f, 0xed, 0xcb, 0x23, 0x2a, 0x05, - 0x1b, 0xe4, 0x4d, 0x0d, 0x68, 0x28, 0xae, 0x13, 0x31, 0xf9, 0xc8, 0xd5, 0x04, 0xdf, 0x89, 0x38, - 0xd9, 0x82, 0xc1, 0x42, 0xb6, 0x60, 0x60, 0xfc, 0xeb, 0x2a, 0x94, 0xe5, 0x30, 0x22, 0x97, 0x1f, - 0x3a, 0x17, 0x34, 0xe2, 0xf2, 0xd9, 0x17, 0x13, 0x1e, 0x7c, 0x3a, 0xf5, 0x42, 0x25, 0xdd, 0xf1, - 0x6d, 0x52, 0xe7, 0x40, 0x21, 0xdf, 0x69, 0x12, 0x06, 0x57, 0x92, 0x72, 0xca, 0x27, 0x25, 0x0c, - 0xce, 0x3f, 0xde, 0x82, 0xb2, 0x94, 0x13, 0x8a, 0x4a, 0x47, 0xb2, 0x30, 0xe2, 0x42, 0xc2, 0x26, - 0x54, 0x46, 0xf6, 0xcc, 0x1e, 0x39, 0x21, 0x67, 0xf1, 0x0b, 0xa6, 0xfa, 0x66, 0xa5, 0x4f, 0xbc, - 0x91, 0x3d, 0xb1, 0x4e, 0xec, 0x89, 0xed, 0x8e, 0xa8, 0xd0, 0x3e, 0xd6, 0x11, 0xb8, 0xcd, 0x61, - 0xe4, 0x5b, 0xb0, 0x28, 0xda, 0x29, 0xb1, 0xb8, 0x12, 0x52, 0xb4, 0x5e, 0xa2, 0x31, 0x49, 0xd4, - 0x9b, 0xb2, 0x79, 0x39, 0xa5, 0x5c, 0x66, 0x2b, 0x98, 0x55, 0x0e, 0xd9, 0xa3, 0xd8, 0x5b, 0x91, - 0xfc, 0x82, 0xaf, 0xe1, 0x2a, 0xaf, 0x8a, 0x03, 0xbf, 0xe2, 0xeb, 0x37, 0x2d, 0xb8, 0x15, 0x34, - 0xc1, 0xed, 0x7d, 0x58, 0x9e, 0xbb, 0x01, 0x0d, 0xc3, 0x09, 0x1d, 0xab, 0xb6, 0xd4, 0x10, 0xa9, - 0xa9, 0x12, 0x64, 0x73, 0xb6, 0x60, 0x85, 0xab, 0x4d, 0x03, 0x3b, 0xf4, 0x82, 0x73, 0x27, 0xb0, - 0x02, 0xea, 0x4a, 0xf5, 0xd9, 0x32, 0x26, 0x0d, 0x44, 0xca, 0x80, 0xab, 0x5c, 0x36, 0x12, 0xf8, - 0x3e, 0x1d, 0x51, 0xe7, 0x82, 0x8e, 0x51, 0xa8, 0x2b, 0x98, 0x6b, 0xb1, 0x3c, 0xa6, 0x48, 0x44, - 0x09, 0x7d, 0x3e, 0xb5, 0xe6, 0xb3, 0xb1, 0xcd, 0x98, 0xf7, 0x45, 0x2e, 0x25, 0xb9, 0xf3, 0xe9, - 0x31, 0x87, 0x90, 0x07, 0x20, 0xa5, 0x36, 0xb1, 0x66, 0x96, 0x62, 0x87, 0x11, 0xa3, 0x1a, 0x66, - 0x5d, 0x60, 0x70, 0xa9, 0xf2, 0x8e, 0xbe, 0x59, 0x9a, 0x6c, 0x85, 0xe1, 0xf1, 0x1f, 0x6d, 0x98, - 0x16, 0x94, 0x67, 0xbe, 0x73, 0x61, 0x87, 0xb4, 0xb5, 0xcc, 0xcf, 0x7e, 0xf1, 0xc9, 0x08, 0xb8, - 0xe3, 0x3a, 0xa1, 0x63, 0x87, 0x9e, 0xdf, 0x22, 0x98, 0x16, 0x01, 0xc8, 0x7d, 0x58, 0xc6, 0x75, - 0x12, 0x84, 0x76, 0x38, 0x0f, 0x84, 0xc8, 0xba, 0xc2, 0x45, 0x43, 0x96, 0x30, 0x40, 0x38, 0x4a, - 0xad, 0xe4, 0x33, 0x58, 0xe7, 0x4b, 0x23, 0xb5, 0x35, 0x57, 0x15, 0x43, 0xb2, 0x82, 0x18, 0x3b, - 0xf1, 0x3d, 0xfa, 0x05, 0x6c, 0x88, 0xe5, 0x92, 0xca, 0xb9, 0xa6, 0x72, 0xae, 0x72, 0x94, 0x44, - 0xd6, 0x2d, 0x58, 0x66, 0x4d, 0x73, 0x46, 0x96, 0x28, 0x81, 0xed, 0x8a, 0x75, 0xd6, 0x0b, 0xcc, - 0xb4, 0xc4, 0x13, 0x4d, 0x4c, 0x7b, 0x42, 0xaf, 0xc8, 0xf7, 0x60, 0x89, 0x2f, 0x1f, 0xd4, 0xcb, - 0xe0, 0x91, 0xbd, 0x89, 0x47, 0xf6, 0x9a, 0x18, 0xdc, 0x1d, 0x95, 0x8a, 0xa7, 0xf6, 0xe2, 0x28, - 0xf6, 0xcd, 0xb6, 0xc6, 0xc4, 0x39, 0xa5, 0xec, 0x9c, 0x68, 0x6d, 0xf0, 0xc5, 0x26, 0xbf, 0xd9, - 0xae, 0x9d, 0xcf, 0x30, 0xa5, 0xc5, 0x89, 0x35, 0xff, 0xc2, 0x75, 0x3c, 0xf1, 0x02, 0x2a, 0x15, - 0xee, 0xad, 0x9b, 0x62, 0x43, 0x32, 0xa0, 0x94, 0xaf, 0x98, 0x00, 0xcf, 0xb5, 0x25, 0xca, 0x2c, - 0x72, 0x0b, 0x17, 0x46, 0x83, 0x2b, 0x4d, 0xa4, 0x69, 0x84, 0x31, 0x8c, 0xe7, 0xf6, 0x0b, 0x49, - 0xd6, 0xdf, 0x40, 0x6a, 0x02, 0x0c, 0x24, 0x08, 0xfa, 0x1e, 0x2c, 0x8b, 0x59, 0x88, 0x88, 0x69, - 0xeb, 0x36, 0x1e, 0x91, 0x37, 0x65, 0x1f, 0x53, 0xd4, 0xd6, 0x6c, 0xf2, 0x79, 0xd1, 0xe8, 0xef, - 0x3e, 0x10, 0x39, 0x29, 0x5a, 0x41, 0x6f, 0xbe, 0xaa, 0xa0, 0x65, 0x31, 0x4d, 0x11, 0xc8, 0xf8, - 0xbd, 0x1c, 0xe7, 0xb5, 0x04, 0x76, 0xa0, 0x69, 0xaa, 0x38, 0x5d, 0xb3, 0x3c, 0x77, 0x72, 0x25, - 0x48, 0x1d, 0x70, 0x50, 0xdf, 0x9d, 0x20, 0xad, 0x71, 0x5c, 0x1d, 0x85, 0x1f, 0xde, 0x75, 0x09, - 0x44, 0xa4, 0x3b, 0x50, 0x9b, 0xcd, 0x4f, 0x26, 0xce, 0x88, 0xa3, 0x14, 0x78, 0x29, 0x1c, 0x84, - 0x08, 0x6f, 0x41, 0x5d, 0xac, 0x75, 0x8e, 0x51, 0x44, 0x8c, 0x9a, 0x80, 0x21, 0x0a, 0x32, 0x07, - 0xd4, 0x47, 0x62, 0x57, 0x37, 0xf1, 0xb7, 0xb1, 0x0d, 0xab, 0xf1, 0x46, 0x0b, 0xce, 0xe5, 0x3e, - 0x54, 0x04, 0x25, 0x95, 0x6a, 0xde, 0xc5, 0xf8, 0x68, 0x98, 0x2a, 0xdd, 0xf8, 0x37, 0x25, 0x58, - 0x91, 0x63, 0xc4, 0x26, 0x7b, 0x30, 0x9f, 0x4e, 0x6d, 0x3f, 0x83, 0x44, 0xe7, 0x5e, 0x4e, 0xa2, - 0xf3, 0x29, 0x12, 0x1d, 0x57, 0xe2, 0x71, 0x0a, 0x1f, 0x57, 0xe2, 0xb1, 0xd5, 0xc5, 0x55, 0x07, - 0xba, 0x9d, 0xa9, 0x21, 0xc0, 0x43, 0x6e, 0xcf, 0x4a, 0x1d, 0x28, 0xa5, 0x8c, 0x03, 0x45, 0x3f, - 0x0e, 0x16, 0x12, 0xc7, 0xc1, 0x5b, 0xc0, 0x97, 0xb1, 0x5c, 0x8f, 0x65, 0xae, 0x4d, 0x40, 0x98, - 0x58, 0x90, 0xef, 0xc1, 0x52, 0x92, 0x02, 0x73, 0x52, 0xbf, 0x98, 0x41, 0x7f, 0x9d, 0x29, 0x45, - 0xa6, 0x46, 0x43, 0xae, 0x0a, 0xfa, 0xeb, 0x4c, 0xe9, 0x01, 0xa6, 0x48, 0xfc, 0x0e, 0x00, 0xaf, - 0x1b, 0xb7, 0x31, 0xe0, 0x36, 0x7e, 0x37, 0xb1, 0x32, 0xb5, 0x51, 0xdf, 0x62, 0x1f, 0x73, 0x9f, - 0xe2, 0xbe, 0xae, 0x62, 0x4e, 0xdc, 0xd2, 0x9f, 0xc1, 0xa2, 0x37, 0xa3, 0xae, 0x15, 0x51, 0xc1, - 0x1a, 0x16, 0xd5, 0x14, 0x45, 0x75, 0x25, 0xdc, 0x6c, 0x30, 0x3c, 0xf5, 0x49, 0xbe, 0xe0, 0x83, - 0x4c, 0xb5, 0x9c, 0xf5, 0x6b, 0x72, 0x2e, 0x22, 0x62, 0x94, 0xf5, 0x63, 0x54, 0x94, 0x79, 0x93, - 0x39, 0x37, 0x4d, 0x35, 0x70, 0x1d, 0x49, 0x5d, 0xbd, 0xa9, 0x52, 0x4c, 0x1d, 0xcb, 0xf8, 0x8d, - 0x1c, 0xd4, 0xb4, 0x3e, 0x90, 0x35, 0x58, 0xde, 0xe9, 0xf7, 0x8f, 0x3a, 0x66, 0x7b, 0xd8, 0x7d, - 0xda, 0xb1, 0x76, 0x0e, 0xfa, 0x83, 0x4e, 0xf3, 0x06, 0x03, 0x1f, 0xf4, 0x77, 0xda, 0x07, 0xd6, - 0x5e, 0xdf, 0xdc, 0x91, 0xe0, 0x1c, 0x59, 0x07, 0x62, 0x76, 0x0e, 0xfb, 0xc3, 0x4e, 0x0c, 0x9e, - 0x27, 0x4d, 0xa8, 0x6f, 0x9b, 0x9d, 0xf6, 0xce, 0xbe, 0x80, 0x14, 0xc8, 0x2a, 0x34, 0xf7, 0x8e, - 0x7b, 0xbb, 0xdd, 0xde, 0x63, 0x6b, 0xa7, 0xdd, 0xdb, 0xe9, 0x1c, 0x74, 0x76, 0x9b, 0x45, 0xd2, - 0x80, 0x6a, 0x7b, 0xbb, 0xdd, 0xdb, 0xed, 0xf7, 0x3a, 0xbb, 0xcd, 0x92, 0xf1, 0xc7, 0x39, 0x80, - 0xa8, 0xa1, 0x8c, 0xae, 0x46, 0x4d, 0xd5, 0x8d, 0xc4, 0x6b, 0xa9, 0x4e, 0x71, 0xba, 0xea, 0xc7, - 0xbe, 0xc9, 0x43, 0x28, 0x7b, 0xf3, 0x70, 0xe4, 0x4d, 0xb9, 0x10, 0xb1, 0xf8, 0xb0, 0x95, 0xca, - 0xd7, 0xe7, 0xe9, 0xa6, 0x44, 0x8c, 0x19, 0x82, 0x0b, 0xaf, 0x32, 0x04, 0xc7, 0x2d, 0xce, 0x9c, - 0xaf, 0xd3, 0x2c, 0xce, 0xb7, 0x01, 0x82, 0x17, 0x94, 0xce, 0x50, 0xd3, 0x26, 0x76, 0x41, 0x15, - 0x21, 0x43, 0x26, 0x97, 0xfe, 0x87, 0x1c, 0xac, 0xe1, 0x5a, 0x1a, 0x27, 0x89, 0xd8, 0x5d, 0xa8, - 0x8d, 0x3c, 0x6f, 0x46, 0x19, 0x53, 0xad, 0xf8, 0x35, 0x1d, 0xc4, 0x08, 0x14, 0x27, 0xc8, 0xa7, - 0x9e, 0x3f, 0xa2, 0x82, 0x86, 0x01, 0x82, 0xf6, 0x18, 0x84, 0xed, 0x21, 0xb1, 0x09, 0x39, 0x06, - 0x27, 0x61, 0x35, 0x0e, 0xe3, 0x28, 0xeb, 0xb0, 0x70, 0xe2, 0x53, 0x7b, 0x74, 0x2e, 0xa8, 0x97, - 0xf8, 0x22, 0xdf, 0x8e, 0x34, 0x8e, 0x23, 0xb6, 0x27, 0x26, 0x94, 0x37, 0xbe, 0x62, 0x2e, 0x09, - 0xf8, 0x8e, 0x00, 0xb3, 0x73, 0xde, 0x3e, 0xb1, 0xdd, 0xb1, 0xe7, 0xd2, 0xb1, 0x90, 0xff, 0x23, - 0x80, 0x71, 0x04, 0xeb, 0xc9, 0xfe, 0x09, 0x7a, 0xf7, 0xa9, 0x46, 0xef, 0xb8, 0x50, 0xbc, 0x79, - 0xfd, 0x1e, 0xd3, 0x68, 0xdf, 0x7f, 0x2c, 0x42, 0x91, 0x09, 0x3c, 0xd7, 0xca, 0x46, 0xba, 0x6c, - 0x5b, 0x48, 0xb9, 0x07, 0xa0, 0x62, 0x93, 0x33, 0x60, 0x62, 0xb2, 0x10, 0x82, 0x8c, 0x97, 0x4a, - 0xf6, 0xe9, 0xe8, 0x42, 0xca, 0x2c, 0x08, 0x31, 0xe9, 0xe8, 0x02, 0x15, 0x1d, 0x76, 0xc8, 0xf3, - 0x72, 0x7a, 0x55, 0x0e, 0xec, 0x10, 0x73, 0x8a, 0x24, 0xcc, 0x57, 0x56, 0x49, 0x98, 0xab, 0x05, - 0x65, 0xc7, 0x3d, 0xf1, 0xe6, 0xae, 0x54, 0x2b, 0xc9, 0x4f, 0xf4, 0x46, 0x40, 0x4a, 0xca, 0x8e, - 0x76, 0x4e, 0x8d, 0x2a, 0x0c, 0x30, 0x64, 0x87, 0xfb, 0x47, 0x50, 0x0d, 0xae, 0xdc, 0x91, 0x4e, - 0x83, 0x56, 0xc5, 0xf8, 0xb0, 0xde, 0x6f, 0x0d, 0xae, 0xdc, 0x11, 0xae, 0xf8, 0x4a, 0x20, 0x7e, - 0x91, 0x47, 0x50, 0x51, 0x56, 0x3a, 0x7e, 0x82, 0xdc, 0xd4, 0x73, 0x48, 0xd3, 0x1c, 0xd7, 0xd1, - 0x29, 0x54, 0xf2, 0x21, 0x2c, 0xa0, 0xb6, 0x3e, 0x68, 0xd5, 0x31, 0x93, 0x14, 0x78, 0x59, 0x33, - 0xd0, 0x11, 0x80, 0x8e, 0xd1, 0x66, 0x66, 0x0a, 0x34, 0x36, 0x4c, 0xa7, 0x13, 0x7b, 0x26, 0x74, - 0xe7, 0x0d, 0x6e, 0x4f, 0x67, 0x10, 0xae, 0x38, 0xbf, 0x0b, 0x75, 0xb4, 0x80, 0x22, 0x8e, 0xcb, - 0xf9, 0xd0, 0x82, 0x09, 0x0c, 0xb6, 0x37, 0xb1, 0x67, 0xbd, 0x60, 0xf3, 0x09, 0x34, 0x62, 0x8d, - 0xd1, 0x55, 0x68, 0x0d, 0xae, 0x42, 0x7b, 0x47, 0x57, 0xa1, 0x45, 0x47, 0xa1, 0xc8, 0xa6, 0xab, - 0xd4, 0x8e, 0xa0, 0x22, 0xc7, 0x82, 0xd1, 0x9c, 0xe3, 0xde, 0x93, 0x5e, 0xff, 0xab, 0x9e, 0x35, - 0x78, 0xd6, 0xdb, 0x69, 0xde, 0x20, 0x4b, 0x50, 0x6b, 0xef, 0x20, 0x19, 0x43, 0x40, 0x8e, 0xa1, - 0x1c, 0xb5, 0x07, 0x03, 0x05, 0xc9, 0x33, 0x94, 0xa3, 0x6e, 0xaf, 0xd7, 0xd9, 0xe5, 0x80, 0x82, - 0xb1, 0x07, 0xcd, 0x64, 0xdf, 0xd9, 0x2a, 0x0f, 0x25, 0x4c, 0xd8, 0x25, 0x23, 0x40, 0x64, 0xfd, - 0xc8, 0x6b, 0xd6, 0x0f, 0xe3, 0x11, 0x34, 0xd9, 0x49, 0xcf, 0x06, 0x5f, 0x77, 0x57, 0x98, 0x30, - 0x5e, 0x5c, 0xb7, 0x4d, 0x56, 0xcc, 0x1a, 0x87, 0x61, 0x55, 0xc6, 0xa7, 0xb0, 0xac, 0x65, 0x8b, - 0xf4, 0x47, 0x8c, 0x7b, 0x48, 0xea, 0x8f, 0x50, 0xf2, 0xe7, 0x29, 0xc6, 0x06, 0xac, 0xb1, 0xcf, - 0xce, 0x05, 0x75, 0xc3, 0xc1, 0xfc, 0x84, 0x7b, 0xb9, 0x38, 0x9e, 0x6b, 0xfc, 0x6a, 0x0e, 0xaa, - 0x2a, 0xe5, 0xfa, 0x6d, 0xb3, 0x25, 0x54, 0x4d, 0x9c, 0x4e, 0x6e, 0x6a, 0x35, 0x60, 0xc6, 0x2d, - 0xfc, 0x1b, 0xa9, 0x9c, 0x8c, 0x2d, 0xa8, 0x2a, 0x10, 0x0e, 0x62, 0xa7, 0x63, 0x5a, 0xfd, 0xde, - 0x41, 0xb7, 0xc7, 0x4e, 0x0b, 0x36, 0xce, 0x08, 0xd8, 0xdb, 0x43, 0x48, 0xce, 0x68, 0xc2, 0xe2, - 0x63, 0x1a, 0x76, 0xdd, 0x53, 0x4f, 0x0c, 0x86, 0xf1, 0xeb, 0x0b, 0xb0, 0xa4, 0x40, 0x91, 0x62, - 0xea, 0x82, 0xfa, 0x81, 0xe3, 0xb9, 0xb8, 0x70, 0xaa, 0xa6, 0xfc, 0x64, 0xf4, 0x4e, 0x88, 0x6d, - 0xc8, 0x77, 0xac, 0x62, 0xaa, 0x10, 0xf4, 0x90, 0xe9, 0x78, 0x0f, 0x96, 0x9c, 0x31, 0x75, 0x43, - 0x27, 0xbc, 0xb2, 0x62, 0x36, 0x85, 0x45, 0x09, 0x16, 0x8c, 0xc7, 0x2a, 0x94, 0xec, 0x89, 0x63, - 0x4b, 0xef, 0x21, 0xfe, 0xc1, 0xa0, 0x23, 0x6f, 0xe2, 0xf9, 0x28, 0xc8, 0x54, 0x4d, 0xfe, 0x41, - 0x1e, 0xc0, 0x2a, 0x13, 0xaa, 0x74, 0x23, 0x18, 0x92, 0x2c, 0x6e, 0xde, 0x20, 0xee, 0x7c, 0x7a, - 0x14, 0x19, 0xc2, 0x58, 0x0a, 0x63, 0x37, 0x58, 0x0e, 0xc1, 0x5f, 0xaa, 0x0c, 0x5c, 0x51, 0xb2, - 0xec, 0xce, 0xa7, 0x6d, 0x4c, 0x51, 0xf8, 0x0f, 0x61, 0x8d, 0xe1, 0x2b, 0x8e, 0x54, 0xe5, 0x58, - 0xc2, 0x1c, 0xac, 0xb0, 0xae, 0x48, 0x53, 0x79, 0x6e, 0x41, 0x95, 0xb7, 0x8a, 0x2d, 0x09, 0x61, - 0x2d, 0xc3, 0xa6, 0x50, 0x3f, 0x48, 0x39, 0xfa, 0x70, 0xcd, 0x40, 0xd2, 0xd1, 0x47, 0x73, 0x15, - 0xaa, 0x24, 0x5d, 0x85, 0x1e, 0xc2, 0xda, 0x09, 0x5b, 0xa3, 0xe7, 0xd4, 0x1e, 0x53, 0xdf, 0x8a, - 0x56, 0x3e, 0x97, 0x3f, 0x57, 0x58, 0xe2, 0x3e, 0xa6, 0xa9, 0x8d, 0xc2, 0x58, 0x43, 0x46, 0x89, - 0xe8, 0xd8, 0x0a, 0x3d, 0x0b, 0x39, 0x46, 0xa1, 0xb6, 0x6d, 0x70, 0xf0, 0xd0, 0xdb, 0x61, 0xc0, - 0x38, 0xde, 0x99, 0x6f, 0xcf, 0xce, 0x85, 0x74, 0xa8, 0xf0, 0x1e, 0x33, 0x20, 0x79, 0x03, 0xca, - 0x6c, 0x4f, 0xb8, 0x94, 0x7b, 0x47, 0x70, 0xb9, 0x4b, 0x82, 0xc8, 0x3b, 0xb0, 0x80, 0x75, 0x04, - 0xad, 0x26, 0x6e, 0x88, 0x7a, 0x74, 0x76, 0x38, 0xae, 0x29, 0xd2, 0x18, 0xff, 0x3d, 0xf7, 0x1d, - 0x4e, 0xd8, 0xaa, 0x26, 0xfe, 0x26, 0xdf, 0xd7, 0xa8, 0xe4, 0x0a, 0xe6, 0x7d, 0x47, 0xe4, 0x4d, - 0x2c, 0xc5, 0xeb, 0x08, 0xe6, 0x37, 0x4a, 0xbe, 0x7e, 0x50, 0xac, 0xd4, 0x9a, 0x75, 0xa3, 0x85, - 0xfe, 0x4d, 0x26, 0x1d, 0x79, 0x17, 0xd4, 0xbf, 0x8a, 0xed, 0x91, 0x1c, 0x6c, 0xa4, 0x92, 0x22, - 0x4f, 0x07, 0x5f, 0xc0, 0xad, 0xa9, 0x37, 0x96, 0x5c, 0x42, 0x5d, 0x02, 0x0f, 0xbd, 0x31, 0xe3, - 0x66, 0x96, 0x15, 0xd2, 0xa9, 0xe3, 0x3a, 0xc1, 0x39, 0x1d, 0x0b, 0x66, 0xa1, 0x29, 0x13, 0xf6, - 0x04, 0x9c, 0xb1, 0xe4, 0x33, 0xdf, 0x3b, 0x53, 0x67, 0x67, 0xce, 0x54, 0xdf, 0xc6, 0x67, 0x50, - 0xe2, 0x33, 0xc8, 0x36, 0x0a, 0xce, 0x6f, 0x4e, 0x6c, 0x14, 0x84, 0xb6, 0xa0, 0xec, 0xd2, 0xf0, - 0x85, 0xe7, 0x3f, 0x97, 0x1a, 0x68, 0xf1, 0x69, 0xfc, 0x18, 0xb5, 0xac, 0xca, 0x51, 0x8d, 0x6b, - 0x23, 0xd8, 0x12, 0xe6, 0x4b, 0x30, 0x38, 0xb7, 0x85, 0xe2, 0xb7, 0x82, 0x80, 0xc1, 0xb9, 0x9d, - 0x5a, 0xc2, 0xf9, 0xb4, 0xaf, 0xda, 0x3b, 0xb0, 0x28, 0x5d, 0xe3, 0x02, 0x6b, 0x42, 0x4f, 0x43, - 0xb1, 0x25, 0xeb, 0xc2, 0x2f, 0x2e, 0x38, 0xa0, 0xa7, 0xa1, 0x71, 0x08, 0xcb, 0x62, 0xd3, 0xf4, - 0x67, 0x54, 0x56, 0xfd, 0x79, 0x96, 0x98, 0x54, 0x7b, 0xb8, 0x12, 0xe7, 0x3f, 0x38, 0xa7, 0x17, - 0x93, 0x9d, 0x8c, 0x1f, 0x46, 0x2a, 0x45, 0xc6, 0x9d, 0x88, 0xf2, 0x84, 0xb0, 0x22, 0x0d, 0xaa, - 0xd2, 0x69, 0x43, 0x89, 0x44, 0xce, 0x98, 0x8d, 0x4e, 0x30, 0x1f, 0x8d, 0xa4, 0xcb, 0x62, 0xc5, - 0x94, 0x9f, 0xc6, 0xff, 0xcc, 0xc1, 0x0a, 0x16, 0x26, 0xc5, 0x3c, 0x71, 0x52, 0xfc, 0xc4, 0x8d, - 0x64, 0xf3, 0xa3, 0xb3, 0x84, 0xfc, 0xe3, 0xd5, 0x16, 0xa1, 0xa4, 0xb5, 0xa7, 0x98, 0x69, 0xed, - 0xf9, 0x36, 0x34, 0xc7, 0x74, 0xe2, 0xe0, 0x72, 0x92, 0x5c, 0x16, 0x67, 0x6b, 0x97, 0x24, 0x5c, - 0xaa, 0x1e, 0x52, 0x26, 0xa6, 0x85, 0xb4, 0xf9, 0xf1, 0xaf, 0xe6, 0x60, 0x99, 0x33, 0x7a, 0xa8, - 0xf0, 0x11, 0x03, 0xfa, 0xa5, 0xd4, 0x6c, 0x08, 0xb2, 0x2b, 0xfa, 0x1e, 0x31, 0x40, 0x08, 0xe5, - 0xc8, 0xfb, 0x37, 0x84, 0xc6, 0x43, 0x40, 0xc9, 0x77, 0x51, 0x84, 0x75, 0x2d, 0x04, 0x0a, 0x06, - 0xfe, 0x66, 0x06, 0x6b, 0xa9, 0xb2, 0x33, 0xf9, 0xd6, 0x45, 0xd0, 0x76, 0x05, 0x16, 0xb8, 0xfa, - 0xcc, 0xd8, 0x83, 0x46, 0xac, 0x9a, 0x98, 0x59, 0xa9, 0xce, 0xcd, 0x4a, 0x29, 0x9b, 0x77, 0x3e, - 0x6d, 0xf3, 0xbe, 0x82, 0x15, 0x93, 0xda, 0xe3, 0xab, 0x3d, 0xcf, 0x3f, 0x0a, 0x4e, 0xc2, 0x3d, - 0xce, 0x3d, 0xb3, 0xb3, 0x4a, 0x79, 0xb9, 0xc4, 0xec, 0x30, 0xd2, 0x9e, 0x2f, 0x07, 0xf1, 0x5b, - 0xb0, 0x18, 0xb9, 0xc3, 0x68, 0x1a, 0xfb, 0x86, 0xf2, 0x88, 0x41, 0xa6, 0x8b, 0x40, 0x71, 0x16, - 0x9c, 0x84, 0x42, 0x67, 0x8f, 0xbf, 0x8d, 0x7f, 0x54, 0x02, 0xc2, 0x56, 0x7d, 0x62, 0x61, 0xa5, - 0xa6, 0x25, 0x97, 0xb6, 0xfc, 0x25, 0x9c, 0x7d, 0xf2, 0x29, 0x67, 0x9f, 0x07, 0x40, 0x34, 0x04, - 0xe9, 0x83, 0x54, 0x50, 0x3e, 0x48, 0xcd, 0x08, 0x57, 0xb8, 0x20, 0x3d, 0x80, 0x55, 0x21, 0xae, - 0xc4, 0xbb, 0x83, 0xcb, 0xcc, 0x24, 0x5c, 0x6e, 0x89, 0xf5, 0x49, 0x3a, 0xfa, 0x48, 0x35, 0x78, - 0x81, 0x3b, 0xfa, 0x48, 0x6d, 0x95, 0xb6, 0x98, 0x17, 0x5e, 0xb9, 0x98, 0xcb, 0x99, 0x8b, 0x59, - 0xd3, 0x5e, 0x56, 0xe2, 0xda, 0xcb, 0x94, 0x1e, 0x9e, 0xf3, 0xe7, 0x31, 0x3d, 0xfc, 0x3d, 0x68, - 0x4a, 0x4d, 0x96, 0xd2, 0x91, 0x0a, 0x0f, 0x10, 0xa1, 0xac, 0x92, 0x5a, 0xd2, 0x98, 0xa1, 0xb1, - 0xf6, 0x3a, 0x16, 0xcf, 0x7a, 0xb6, 0xc5, 0x33, 0xad, 0xf3, 0x6b, 0x64, 0xe8, 0xfc, 0x1e, 0x45, - 0x0e, 0x1e, 0xc1, 0xb9, 0x33, 0x45, 0x46, 0x2a, 0xf2, 0x50, 0x15, 0x83, 0x3c, 0x38, 0x77, 0xa6, - 0xa6, 0x74, 0xb5, 0x62, 0x1f, 0x64, 0x07, 0xee, 0x88, 0xfe, 0x64, 0x78, 0x49, 0xf1, 0x51, 0x58, - 0xc2, 0xa5, 0xb2, 0xc9, 0xd1, 0x0e, 0x13, 0x0e, 0x53, 0x89, 0x41, 0x91, 0x3e, 0x36, 0x01, 0x57, - 0x1c, 0xcb, 0x41, 0x39, 0xe4, 0x4e, 0x36, 0x48, 0x1e, 0x18, 0x8a, 0x50, 0x2a, 0x06, 0x17, 0xc8, - 0x77, 0x35, 0xcc, 0xda, 0xd4, 0xbe, 0x3c, 0x40, 0xa5, 0x61, 0x70, 0x61, 0xfc, 0x69, 0x0e, 0x9a, - 0x6c, 0x09, 0xc7, 0xa8, 0xc3, 0x17, 0x80, 0xf4, 0xee, 0x35, 0x89, 0x43, 0x8d, 0xe1, 0x4a, 0xda, - 0xf0, 0x19, 0xe0, 0x66, 0xb7, 0xbc, 0x19, 0x75, 0x05, 0x69, 0x68, 0xc5, 0x49, 0x43, 0x74, 0x4c, - 0xec, 0xdf, 0xe0, 0x52, 0x27, 0x83, 0x90, 0x2f, 0xa0, 0xca, 0xf6, 0x14, 0x2e, 0x5e, 0xe1, 0x1d, - 0xbe, 0xa9, 0x34, 0x09, 0xa9, 0xed, 0xcd, 0xb2, 0xce, 0xc4, 0x67, 0x96, 0x0b, 0x55, 0x31, 0xc3, - 0x85, 0x4a, 0xa3, 0x3d, 0xfb, 0x00, 0x4f, 0xe8, 0x15, 0x1b, 0x84, 0xd0, 0xf3, 0x19, 0xaf, 0xc6, - 0xb6, 0xd8, 0xa9, 0x3d, 0x75, 0x84, 0x36, 0xb3, 0x64, 0x56, 0x9f, 0xd3, 0xab, 0x3d, 0x04, 0xb0, - 0xb5, 0xc5, 0x92, 0x23, 0x02, 0x54, 0x32, 0x2b, 0xcf, 0xe9, 0x15, 0xa7, 0x3e, 0x16, 0x34, 0x9e, - 0xd0, 0xab, 0x5d, 0xca, 0x85, 0x01, 0xcf, 0x67, 0x83, 0xee, 0xdb, 0x2f, 0x18, 0xf7, 0x1f, 0x73, - 0xf1, 0xa9, 0xf9, 0xf6, 0x8b, 0x27, 0xf4, 0x4a, 0xba, 0x1b, 0x95, 0x59, 0xfa, 0xc4, 0x1b, 0x09, - 0xf6, 0x45, 0x2a, 0x90, 0xa2, 0x46, 0x99, 0x0b, 0xcf, 0xf1, 0xb7, 0xf1, 0x27, 0x39, 0x68, 0xb0, - 0xf6, 0xe3, 0xc9, 0x83, 0xab, 0x48, 0xf8, 0x0c, 0xe7, 0x22, 0x9f, 0xe1, 0x87, 0x82, 0x20, 0xf3, - 0x63, 0x2c, 0x7f, 0xfd, 0x31, 0x86, 0x73, 0xc3, 0xcf, 0xb0, 0x8f, 0xa0, 0xca, 0x17, 0x06, 0x23, - 0x3f, 0x85, 0xd8, 0x04, 0xc7, 0x3a, 0x64, 0x56, 0x10, 0xed, 0x09, 0xf7, 0x3f, 0xd4, 0x74, 0xf5, - 0x7c, 0x88, 0xab, 0xbe, 0xd2, 0xd0, 0x67, 0x4c, 0x43, 0xe9, 0x1a, 0xff, 0x43, 0x5d, 0x11, 0xbe, - 0x90, 0x54, 0x84, 0x1b, 0x2e, 0x54, 0xd8, 0x54, 0x63, 0x67, 0x33, 0x0a, 0xcd, 0x65, 0x15, 0xca, - 0x98, 0x1d, 0x9b, 0x9d, 0x67, 0x8c, 0x46, 0xe7, 0x05, 0xb3, 0x63, 0x07, 0x94, 0x15, 0xc4, 0x1a, - 0xee, 0x7a, 0x16, 0x6a, 0x96, 0x85, 0xce, 0xb5, 0x62, 0x56, 0x5d, 0xef, 0x88, 0x03, 0x8c, 0xbf, - 0x90, 0x83, 0x9a, 0xb6, 0x67, 0xd1, 0xd4, 0xa0, 0x86, 0x93, 0x6f, 0xf0, 0xf8, 0x0e, 0x88, 0xcd, - 0xc7, 0xfe, 0x0d, 0xb3, 0x31, 0x8a, 0x4d, 0xd0, 0x96, 0x58, 0xca, 0x98, 0x33, 0x1f, 0xd3, 0x6f, - 0xc9, 0x7e, 0xc9, 0xf5, 0xcb, 0x7e, 0x6f, 0x2f, 0x40, 0x91, 0xa1, 0x1a, 0x5f, 0xc2, 0xb2, 0xd6, - 0x0c, 0xae, 0xff, 0x79, 0xdd, 0x01, 0x30, 0x7e, 0x41, 0x65, 0x66, 0x75, 0x70, 0xdb, 0xbd, 0x74, - 0xf5, 0xa4, 0x63, 0x3e, 0x2e, 0xc2, 0xa5, 0x94, 0x83, 0x70, 0x64, 0x5e, 0xd3, 0xfb, 0xd0, 0xf8, - 0x95, 0x1c, 0xac, 0x68, 0xc5, 0xef, 0x39, 0xae, 0x3d, 0x71, 0x7e, 0x8c, 0xc7, 0x58, 0xe0, 0x9c, - 0xb9, 0x89, 0x0a, 0x38, 0xe8, 0xeb, 0x54, 0x40, 0xee, 0x42, 0x9d, 0xfb, 0x96, 0xf3, 0x9b, 0x0b, - 0xe2, 0x98, 0x05, 0x84, 0x99, 0xf6, 0x8b, 0xe1, 0xa5, 0xf1, 0xd7, 0xf2, 0xb0, 0x2a, 0x9a, 0x80, - 0x57, 0x00, 0x1c, 0xc6, 0xea, 0x1e, 0x06, 0x67, 0xe4, 0x0b, 0x68, 0xb0, 0xe1, 0xb3, 0x7c, 0x7a, - 0xe6, 0x04, 0x21, 0x95, 0x6e, 0x05, 0x19, 0xd4, 0x98, 0x71, 0x32, 0x0c, 0xd5, 0x14, 0x98, 0xe4, - 0x4b, 0xa8, 0x61, 0x56, 0xae, 0x82, 0x13, 0x73, 0xd5, 0x4a, 0x67, 0xe4, 0x73, 0xb1, 0x7f, 0xc3, - 0x84, 0x20, 0x9a, 0x99, 0x2f, 0xa1, 0x86, 0xd3, 0x7c, 0x81, 0x63, 0x9d, 0x20, 0x76, 0xa9, 0xb9, - 0x60, 0x99, 0x67, 0xd1, 0xcc, 0xb4, 0xa1, 0xc1, 0xc9, 0x9d, 0x18, 0x49, 0xe1, 0x37, 0xbc, 0x99, - 0xce, 0x2e, 0xc7, 0x9a, 0x35, 0x7e, 0xa6, 0x7d, 0x6f, 0x57, 0xa1, 0x1c, 0xfa, 0xce, 0xd9, 0x19, - 0xf5, 0x8d, 0x75, 0x35, 0x34, 0x8c, 0x8e, 0xd3, 0x41, 0x48, 0x67, 0x4c, 0x86, 0x31, 0xfe, 0x59, - 0x0e, 0x6a, 0x82, 0x32, 0xff, 0xc4, 0x1e, 0x0b, 0x9b, 0x09, 0x65, 0x6d, 0x55, 0xd3, 0xcd, 0xbe, - 0x07, 0x4b, 0x53, 0x26, 0x70, 0x39, 0xe1, 0x55, 0xdc, 0x5d, 0x61, 0x51, 0x82, 0x85, 0x2c, 0xb1, - 0x05, 0x2b, 0x28, 0x5a, 0x04, 0x56, 0xe8, 0x4c, 0x2c, 0x99, 0x28, 0x6e, 0xc8, 0x2c, 0xf3, 0xa4, - 0xa1, 0x33, 0x39, 0x14, 0x09, 0x8c, 0xc3, 0x0e, 0x42, 0xfb, 0x8c, 0x0a, 0xea, 0xc0, 0x3f, 0x98, - 0x10, 0x97, 0xd0, 0x05, 0x48, 0x21, 0xee, 0x7f, 0x2f, 0xc3, 0x46, 0x2a, 0x49, 0x08, 0x71, 0xca, - 0x3a, 0x3c, 0x71, 0xa6, 0x27, 0x9e, 0xb2, 0x4e, 0xe4, 0x34, 0xeb, 0xf0, 0x01, 0x4b, 0x91, 0xd6, - 0x09, 0x0a, 0x6b, 0x72, 0xc9, 0xa2, 0x79, 0x41, 0xa9, 0x0b, 0xf2, 0x28, 0xcc, 0x7e, 0x14, 0x3f, - 0x06, 0x93, 0xd5, 0x49, 0xb8, 0xce, 0x17, 0xae, 0xcc, 0x52, 0xb0, 0x80, 0xfc, 0xff, 0xd0, 0x52, - 0x3b, 0x43, 0xc8, 0x36, 0x9a, 0xee, 0x83, 0xd5, 0xf4, 0x9d, 0x57, 0xd4, 0x14, 0xd3, 0xfb, 0x22, - 0xeb, 0xb5, 0x2e, 0x37, 0x15, 0x2f, 0x50, 0xd5, 0x75, 0x01, 0x6f, 0xca, 0xba, 0x50, 0x56, 0x49, - 0xd7, 0x58, 0x7c, 0xad, 0xbe, 0xa1, 0x4e, 0x3b, 0x56, 0xad, 0x79, 0x4b, 0x14, 0xac, 0x92, 0xf4, - 0x7a, 0xcf, 0x61, 0xfd, 0x85, 0xed, 0x84, 0xb2, 0x8f, 0x9a, 0xea, 0xa5, 0x84, 0xf5, 0x3d, 0x7c, - 0x45, 0x7d, 0x5f, 0xf1, 0xcc, 0x31, 0xe9, 0x6d, 0xf5, 0x45, 0x1a, 0x18, 0x6c, 0xfe, 0xed, 0x02, - 0x2c, 0xc6, 0x4b, 0x61, 0xa4, 0x47, 0x1c, 0x57, 0x92, 0x91, 0x16, 0x12, 0x80, 0xb0, 0x9c, 0xf5, - 0x38, 0x03, 0x9d, 0xb6, 0xe9, 0xe5, 0x33, 0x6c, 0x7a, 0xba, 0x29, 0xad, 0xf0, 0x2a, 0xcf, 0x8a, - 0xe2, 0x6b, 0x79, 0x56, 0x94, 0xb2, 0x3c, 0x2b, 0x3e, 0xbe, 0xd6, 0x14, 0xcf, 0x15, 0xe2, 0x99, - 0x66, 0xf8, 0x47, 0xd7, 0x9b, 0xe1, 0xb9, 0xae, 0xfc, 0x3a, 0x13, 0xbc, 0xe6, 0x40, 0x50, 0xb9, - 0xc6, 0x00, 0xa6, 0xb9, 0x14, 0x64, 0x98, 0xe0, 0xab, 0x5f, 0xc3, 0x04, 0xbf, 0xf9, 0x27, 0x39, - 0x20, 0xe9, 0xdd, 0x41, 0x1e, 0x73, 0x73, 0xa9, 0x4b, 0x27, 0x82, 0x72, 0x7f, 0xf0, 0x7a, 0x3b, - 0x4c, 0x2e, 0x08, 0x99, 0x9b, 0x7c, 0x08, 0x2b, 0xfa, 0x3d, 0x3e, 0x5d, 0xb5, 0xd1, 0x30, 0x89, - 0x9e, 0x14, 0x29, 0xe9, 0x34, 0x37, 0x96, 0xe2, 0x2b, 0xdd, 0x58, 0x4a, 0xaf, 0x74, 0x63, 0x59, - 0x88, 0xbb, 0xb1, 0x6c, 0xfe, 0xcb, 0x1c, 0xac, 0x64, 0x2c, 0xe2, 0x6f, 0xae, 0xcf, 0x6c, 0xed, - 0xc5, 0xc8, 0x5a, 0x5e, 0xac, 0x3d, 0x9d, 0xa2, 0x1d, 0x48, 0xc5, 0x2e, 0x9b, 0x8a, 0x40, 0x9c, - 0x54, 0xf7, 0x5f, 0x45, 0x5d, 0xa2, 0x1c, 0xa6, 0x9e, 0x7d, 0xf3, 0xef, 0xe4, 0xa1, 0xa6, 0x25, - 0xb2, 0x51, 0xe4, 0x4b, 0x56, 0x73, 0x0a, 0xe5, 0xbc, 0x25, 0x2a, 0x66, 0xf0, 0x6a, 0x01, 0x2e, - 0x4e, 0x4c, 0xe7, 0x9b, 0x4b, 0x30, 0x92, 0x88, 0xb0, 0x05, 0x2b, 0xd2, 0x94, 0x4d, 0x23, 0xa7, - 0x79, 0x71, 0xd6, 0x08, 0xaf, 0x04, 0xd1, 0x48, 0xc4, 0xff, 0x50, 0xca, 0xb9, 0xd1, 0xdc, 0x69, - 0xa6, 0xc1, 0x65, 0xe1, 0x0f, 0x21, 0x26, 0x91, 0xad, 0xf3, 0x8f, 0x60, 0x4d, 0x39, 0x44, 0xc4, - 0x72, 0x70, 0x03, 0x14, 0x91, 0x8e, 0x0f, 0x5a, 0x96, 0xef, 0xc3, 0xed, 0x44, 0x9b, 0x12, 0x59, - 0xb9, 0xa6, 0xe5, 0x66, 0xac, 0x75, 0x7a, 0x09, 0x9b, 0x7f, 0x0e, 0x1a, 0x31, 0x42, 0xf9, 0xcd, - 0x4d, 0x79, 0x52, 0x19, 0xc6, 0x47, 0x54, 0x57, 0x86, 0x6d, 0xfe, 0xf7, 0x02, 0x90, 0x34, 0xad, - 0xfe, 0x69, 0x36, 0x21, 0xbd, 0x30, 0x0b, 0x19, 0x0b, 0xf3, 0xff, 0x19, 0xff, 0x10, 0xe9, 0x64, - 0x35, 0x7f, 0x04, 0xbe, 0x39, 0x9b, 0x2a, 0x41, 0xb6, 0xe2, 0xb3, 0xa4, 0xd7, 0x56, 0x25, 0x76, - 0xe1, 0x54, 0x63, 0xa0, 0x12, 0xce, 0x5b, 0xc7, 0xb0, 0x60, 0xbb, 0xa3, 0x73, 0xcf, 0x17, 0x74, - 0xf0, 0x67, 0xbe, 0xf6, 0xf1, 0xb9, 0xd5, 0xc6, 0xfc, 0xc8, 0xb5, 0x99, 0xa2, 0x30, 0xe3, 0x23, - 0xa8, 0x69, 0x60, 0x52, 0x85, 0xd2, 0x41, 0xf7, 0x70, 0xbb, 0xdf, 0xbc, 0x41, 0x1a, 0x50, 0x35, - 0x3b, 0x3b, 0xfd, 0xa7, 0x1d, 0xb3, 0xb3, 0xdb, 0xcc, 0x91, 0x0a, 0x14, 0x0f, 0xfa, 0x83, 0x61, - 0x33, 0x6f, 0x6c, 0x42, 0x4b, 0x94, 0x98, 0xb6, 0x4e, 0xfd, 0x56, 0x51, 0xe9, 0x54, 0x31, 0x51, - 0x08, 0xf9, 0x1f, 0x43, 0x5d, 0x67, 0x6f, 0xc4, 0x8a, 0x48, 0xb8, 0xc4, 0x30, 0xf1, 0xde, 0xd3, - 0x68, 0xf5, 0x0e, 0x70, 0x87, 0x88, 0xb1, 0xca, 0x96, 0x8f, 0xf1, 0xad, 0x19, 0x96, 0x65, 0x94, - 0x8f, 0x62, 0xcb, 0xf0, 0xff, 0x83, 0xc5, 0xb8, 0x25, 0x46, 0x50, 0xa4, 0x2c, 0x91, 0x95, 0xe5, - 0x8e, 0x99, 0x66, 0xc8, 0xf7, 0xa1, 0x99, 0xb4, 0xe4, 0x08, 0xe6, 0xf9, 0x9a, 0xfc, 0x4b, 0x4e, - 0xdc, 0xb8, 0x43, 0xf6, 0x61, 0x35, 0x8b, 0xc1, 0xc3, 0xf5, 0x71, 0xbd, 0x9a, 0x83, 0xa4, 0x99, - 0x38, 0xf2, 0xb9, 0xb0, 0xe8, 0x95, 0x70, 0xfa, 0xdf, 0x89, 0xd7, 0xaf, 0x0d, 0xf6, 0x16, 0xff, - 0xa7, 0xd9, 0xf6, 0x2e, 0x00, 0x22, 0x18, 0x69, 0x42, 0xbd, 0x7f, 0xd4, 0xe9, 0x59, 0x3b, 0xfb, - 0xed, 0x5e, 0xaf, 0x73, 0xd0, 0xbc, 0x41, 0x08, 0x2c, 0xa2, 0x57, 0xc7, 0xae, 0x82, 0xe5, 0x18, - 0x4c, 0x98, 0x5a, 0x25, 0x2c, 0x4f, 0x56, 0xa1, 0xd9, 0xed, 0x25, 0xa0, 0x05, 0xd2, 0x82, 0xd5, - 0xa3, 0x0e, 0x77, 0x04, 0x89, 0x95, 0x5b, 0x64, 0x42, 0x83, 0xe8, 0xae, 0x11, 0xc2, 0xea, 0x57, - 0xf6, 0x64, 0x42, 0xc3, 0x36, 0x77, 0x64, 0x97, 0xdb, 0xe1, 0x7d, 0x58, 0x56, 0xea, 0xb0, 0x04, - 0xb7, 0xdc, 0x54, 0x09, 0x12, 0xf9, 0x43, 0x58, 0xd1, 0xb4, 0x6a, 0x89, 0x53, 0x88, 0x68, 0x49, - 0x22, 0x03, 0x13, 0x55, 0x78, 0xad, 0x02, 0x20, 0x39, 0xf8, 0x3f, 0xcc, 0xc3, 0x5a, 0x22, 0x21, - 0x32, 0xc2, 0x70, 0xfe, 0x3d, 0xde, 0x96, 0x3a, 0x02, 0x5f, 0xda, 0xe8, 0xfc, 0xd7, 0x6b, 0x74, - 0xe1, 0xba, 0x46, 0x93, 0x67, 0xb0, 0x24, 0xbc, 0xfd, 0x35, 0x1e, 0x8f, 0xd1, 0x88, 0x07, 0x62, - 0xca, 0x33, 0x5b, 0xbe, 0x15, 0x1f, 0x58, 0x6e, 0xe5, 0x5a, 0xb4, 0x63, 0xc0, 0xcd, 0x5f, 0x82, - 0x95, 0x0c, 0xb4, 0x8c, 0x3b, 0x2f, 0x1f, 0xc5, 0x2d, 0x5e, 0xb7, 0x62, 0x35, 0xc7, 0x8b, 0xd0, - 0xad, 0xf7, 0x5b, 0xb0, 0x20, 0xb4, 0xbd, 0x4d, 0x28, 0xc8, 0x6b, 0x4f, 0x45, 0x93, 0xfd, 0x24, - 0x04, 0x8a, 0xd3, 0xc8, 0x01, 0x1b, 0x7f, 0x1b, 0x1b, 0xea, 0x02, 0x63, 0x62, 0x82, 0x7e, 0xa5, - 0x08, 0xeb, 0xc9, 0x14, 0x75, 0x25, 0xa1, 0x1c, 0x9b, 0x1b, 0x6e, 0x49, 0x14, 0x20, 0xf2, 0x49, - 0x62, 0xbb, 0xc5, 0x66, 0x07, 0x51, 0xf5, 0xad, 0x25, 0x87, 0xfc, 0x61, 0x92, 0xa9, 0xe6, 0x34, - 0xa2, 0x21, 0x2f, 0x68, 0x60, 0x9f, 0x12, 0x3c, 0xf6, 0x27, 0x29, 0x1e, 0xbb, 0x98, 0x95, 0x29, - 0xc1, 0x72, 0x77, 0x60, 0x23, 0x72, 0x35, 0x8e, 0xd7, 0x59, 0xca, 0xca, 0xbe, 0xa6, 0xb0, 0x0f, - 0xf4, 0xca, 0x1f, 0x43, 0x2b, 0x2a, 0x26, 0xd1, 0x8c, 0x85, 0xac, 0x72, 0xd6, 0x15, 0xba, 0x19, - 0x6b, 0xcf, 0x0f, 0x60, 0x33, 0x36, 0x5e, 0xf1, 0x26, 0x95, 0xb3, 0x8a, 0xda, 0xd0, 0x06, 0x30, - 0xd6, 0xa8, 0x03, 0xb8, 0x15, 0x2b, 0x2b, 0xd1, 0xae, 0x4a, 0x56, 0x61, 0x2d, 0xad, 0xb0, 0x58, - 0xcb, 0x8c, 0xdf, 0x59, 0x00, 0xf2, 0xc3, 0x39, 0xf5, 0xaf, 0xf0, 0x5a, 0x73, 0xf0, 0xaa, 0x3b, - 0x14, 0x52, 0x53, 0x99, 0x7f, 0xad, 0xe8, 0x06, 0x59, 0xd1, 0x05, 0x8a, 0xaf, 0x8e, 0x2e, 0x50, - 0x7a, 0x55, 0x74, 0x81, 0xb7, 0xa1, 0xe1, 0x9c, 0xb9, 0x1e, 0x63, 0x04, 0x98, 0x1c, 0x18, 0xb4, - 0x16, 0xee, 0x16, 0xee, 0xd5, 0xcd, 0xba, 0x00, 0x32, 0x29, 0x30, 0x20, 0x5f, 0x46, 0x48, 0x74, - 0x7c, 0x86, 0xb1, 0x37, 0x74, 0x16, 0xa0, 0x33, 0x3e, 0xa3, 0x42, 0x31, 0x8b, 0x0b, 0x56, 0x66, - 0x66, 0xf0, 0x80, 0xbc, 0x03, 0x8b, 0x81, 0x37, 0x67, 0x62, 0xb5, 0x1c, 0x06, 0x6e, 0xef, 0xaf, - 0x73, 0xe8, 0x91, 0xf4, 0xfe, 0x58, 0x99, 0x07, 0xd4, 0x9a, 0x3a, 0x41, 0xc0, 0x84, 0x93, 0x91, - 0xe7, 0x86, 0xbe, 0x37, 0x11, 0x26, 0xfc, 0xe5, 0x79, 0x40, 0x0f, 0x79, 0xca, 0x0e, 0x4f, 0x20, - 0x9f, 0x44, 0x4d, 0x9a, 0xd9, 0x8e, 0x1f, 0xb4, 0x00, 0x9b, 0x24, 0x7b, 0x8a, 0xd2, 0xab, 0xed, - 0xf8, 0xaa, 0x2d, 0xec, 0x23, 0x48, 0x44, 0x3d, 0xa8, 0x25, 0xa3, 0x1e, 0xfc, 0x72, 0x76, 0xd4, - 0x83, 0x46, 0x8c, 0x98, 0xa5, 0xa7, 0xf8, 0x6b, 0x05, 0x3f, 0x48, 0x07, 0x73, 0x58, 0xfc, 0x3a, - 0xc1, 0x1c, 0x96, 0xb2, 0x82, 0x39, 0x7c, 0x04, 0x35, 0xbc, 0x43, 0x6f, 0x9d, 0xa3, 0x33, 0x33, - 0x77, 0x49, 0x68, 0xea, 0x97, 0xec, 0xf7, 0x1d, 0x37, 0x34, 0xc1, 0x97, 0x3f, 0x83, 0x74, 0x5c, - 0x85, 0xe5, 0xd7, 0x8a, 0xab, 0xf0, 0xcd, 0x04, 0x4d, 0x10, 0x77, 0xfd, 0xb7, 0xa0, 0x22, 0xe7, - 0x89, 0x11, 0xdb, 0x53, 0xdf, 0x9b, 0x4a, 0xf3, 0x26, 0xfb, 0x4d, 0x16, 0x21, 0x1f, 0x7a, 0x22, - 0x73, 0x3e, 0xf4, 0x8c, 0x5f, 0x84, 0x9a, 0xb6, 0xd4, 0xc8, 0x5b, 0x5c, 0xaf, 0xef, 0xd2, 0x89, - 0x54, 0xfb, 0xf2, 0x51, 0xac, 0x0a, 0x68, 0x77, 0xcc, 0xce, 0xbd, 0xb1, 0xe3, 0x53, 0x8c, 0x80, - 0x62, 0xf9, 0xf4, 0x82, 0xfa, 0x81, 0x34, 0x4b, 0x37, 0x55, 0x82, 0xc9, 0xe1, 0xc6, 0x2f, 0xc1, - 0x4a, 0x6c, 0x6e, 0x05, 0xf9, 0x7e, 0x07, 0x16, 0x70, 0xdc, 0xa4, 0xef, 0x53, 0x3c, 0x78, 0x81, - 0x48, 0xc3, 0x38, 0x30, 0xdc, 0xa2, 0x6e, 0xcd, 0x7c, 0xef, 0x04, 0x2b, 0xc9, 0x99, 0x35, 0x01, - 0x3b, 0xf2, 0xbd, 0x13, 0xe3, 0xdf, 0x17, 0xa0, 0xb0, 0xef, 0xcd, 0x74, 0x07, 0xe8, 0x5c, 0xca, - 0x01, 0x5a, 0xa8, 0x5b, 0x2c, 0xa5, 0x4e, 0x11, 0x12, 0x2b, 0xda, 0x88, 0xa5, 0x4a, 0xe5, 0x1e, - 0x2c, 0x32, 0x3a, 0x11, 0x7a, 0x96, 0xb8, 0x78, 0xc4, 0x0f, 0x67, 0xbe, 0xf9, 0xec, 0x69, 0x38, - 0xf4, 0xf6, 0x38, 0x9c, 0xac, 0x42, 0x41, 0x09, 0xef, 0x98, 0xcc, 0x3e, 0xc9, 0x3a, 0x2c, 0xe0, - 0x85, 0x29, 0x79, 0xd3, 0x5d, 0x7c, 0x91, 0x0f, 0x60, 0x25, 0x5e, 0x2e, 0x27, 0x45, 0x42, 0x32, - 0xd0, 0x0b, 0x46, 0x9a, 0x74, 0x13, 0x18, 0x1d, 0x89, 0xee, 0xba, 0x17, 0xcc, 0xf2, 0x29, 0xa5, - 0x98, 0xa4, 0x11, 0xbd, 0x4a, 0x8c, 0xe8, 0xdd, 0x81, 0x5a, 0x38, 0xb9, 0xb0, 0x66, 0xf6, 0xd5, - 0xc4, 0xb3, 0xe5, 0xcd, 0x4a, 0x08, 0x27, 0x17, 0x47, 0x1c, 0x42, 0x3e, 0x04, 0x98, 0xce, 0x66, - 0x62, 0xef, 0xa1, 0x3d, 0x33, 0x5a, 0xca, 0x87, 0x47, 0x47, 0x7c, 0xc9, 0x99, 0xd5, 0xe9, 0x6c, - 0xc6, 0x7f, 0x92, 0x5d, 0x58, 0xcc, 0x8c, 0x52, 0x72, 0x5b, 0x5e, 0x2b, 0xf1, 0x66, 0x5b, 0x19, - 0x9b, 0xb3, 0x31, 0xd2, 0x61, 0x9b, 0xdf, 0x07, 0xf2, 0x67, 0x0c, 0x04, 0x32, 0x84, 0xaa, 0x6a, - 0x5f, 0x2a, 0xfc, 0x48, 0x2d, 0x15, 0x7e, 0x84, 0xd1, 0x45, 0xce, 0xb8, 0x29, 0x92, 0x0f, 0x1a, - 0xe7, 0x26, 0x2e, 0x64, 0x19, 0xff, 0x29, 0x07, 0x25, 0x1e, 0xd4, 0xe3, 0x5d, 0x58, 0xe2, 0xf8, - 0xca, 0x99, 0x5c, 0x78, 0xfc, 0x70, 0xfe, 0x6f, 0x28, 0xfc, 0xc8, 0xd9, 0xb6, 0xd0, 0xa2, 0x24, - 0x45, 0x6c, 0x84, 0x16, 0x29, 0xe9, 0x0e, 0x54, 0x55, 0xd5, 0xda, 0xd2, 0xa9, 0xc8, 0x9a, 0xc9, - 0x9b, 0x50, 0x3c, 0xf7, 0x66, 0x52, 0xef, 0x09, 0xd1, 0x48, 0x9a, 0x08, 0x8f, 0xda, 0xc2, 0xea, - 0x88, 0x2e, 0x8a, 0x15, 0x44, 0x5b, 0x58, 0x25, 0x32, 0xd4, 0x41, 0xa2, 0x8f, 0x0b, 0x19, 0x7d, - 0x3c, 0x86, 0x25, 0x46, 0x07, 0x34, 0xb7, 0xa3, 0xeb, 0x0f, 0xcd, 0x6f, 0x33, 0xf9, 0x66, 0x34, - 0x99, 0x8f, 0xa9, 0xae, 0x79, 0x46, 0xcf, 0x60, 0x01, 0x97, 0x72, 0xa5, 0xf1, 0x3b, 0x39, 0x4e, - 0x5f, 0x58, 0xb9, 0xe4, 0x1e, 0x14, 0x5d, 0xe9, 0xa2, 0x14, 0x49, 0x31, 0xea, 0x52, 0x25, 0xc3, - 0x33, 0x11, 0x83, 0x4d, 0x1d, 0x3a, 0xf6, 0xe8, 0xa5, 0x37, 0xcc, 0x9a, 0x3b, 0x9f, 0x2a, 0xc5, - 0xed, 0xb7, 0x64, 0xb7, 0x12, 0x4a, 0x4f, 0xde, 0x7b, 0xb5, 0x4d, 0xb7, 0x34, 0x17, 0xe3, 0x62, - 0xec, 0xc4, 0x94, 0x32, 0xd0, 0xf8, 0x8c, 0x6a, 0xae, 0xc5, 0xbf, 0x9f, 0x87, 0x46, 0xac, 0x45, - 0xe8, 0x63, 0xcd, 0x0e, 0x00, 0x6e, 0x98, 0x15, 0xf3, 0x8d, 0xae, 0xac, 0x42, 0x4c, 0xd5, 0xc6, - 0x29, 0x1f, 0x1b, 0x27, 0xe5, 0x63, 0x58, 0xd0, 0x7d, 0x0c, 0x1f, 0x40, 0x35, 0x8a, 0x8e, 0x15, - 0x6f, 0x12, 0xab, 0x4f, 0x5e, 0x2d, 0x8d, 0x90, 0x22, 0xaf, 0xc4, 0x92, 0xee, 0x95, 0xf8, 0x3d, - 0xcd, 0x89, 0x6d, 0x01, 0x8b, 0x31, 0xb2, 0x46, 0xf4, 0xa7, 0xe2, 0xc2, 0x66, 0x7c, 0x09, 0x35, - 0xad, 0xf1, 0xba, 0x23, 0x58, 0x2e, 0xe6, 0x08, 0xa6, 0x2e, 0xb0, 0xe7, 0xa3, 0x0b, 0xec, 0xc6, - 0xaf, 0xe5, 0xa1, 0xc1, 0xf6, 0x97, 0xe3, 0x9e, 0x1d, 0x79, 0x13, 0x67, 0x84, 0x86, 0x5a, 0xb5, - 0xc3, 0x04, 0xa3, 0x25, 0xf7, 0x99, 0xd8, 0x62, 0x9c, 0xcf, 0xd2, 0xa3, 0xae, 0x70, 0x22, 0xad, - 0xa2, 0xae, 0x18, 0xd0, 0x60, 0x84, 0x11, 0x4d, 0xae, 0x51, 0x24, 0x2d, 0xb3, 0x76, 0x4a, 0xe9, - 0xb6, 0x1d, 0x70, 0x0a, 0xf9, 0x01, 0xac, 0x30, 0x1c, 0x0c, 0xa9, 0x30, 0x75, 0x26, 0x13, 0x27, - 0xba, 0x99, 0x59, 0x30, 0x9b, 0xa7, 0x94, 0x9a, 0x76, 0x48, 0x0f, 0x59, 0x82, 0x08, 0xbc, 0x55, - 0x19, 0x3b, 0x81, 0x7d, 0x12, 0x79, 0xc2, 0xab, 0x6f, 0xe9, 0xc9, 0x10, 0x39, 0x8b, 0x08, 0x47, - 0x27, 0x11, 0x4f, 0x04, 0xf3, 0x27, 0x56, 0x52, 0x39, 0xb9, 0x92, 0x8c, 0x7f, 0x98, 0x87, 0x9a, - 0xb6, 0x2c, 0x5f, 0xe7, 0x74, 0xbd, 0x9d, 0x32, 0xac, 0x57, 0x75, 0x1b, 0xfa, 0xdb, 0xf1, 0x2a, - 0x0b, 0xea, 0xfa, 0x9e, 0xbe, 0x80, 0x6f, 0x41, 0x95, 0xed, 0xba, 0x8f, 0xd0, 0x00, 0x21, 0x42, - 0xe2, 0x21, 0xe0, 0x68, 0x7e, 0x22, 0x13, 0x1f, 0x62, 0x62, 0x29, 0x4a, 0x7c, 0xc8, 0x12, 0x5f, - 0x76, 0x7d, 0xe7, 0x33, 0xa8, 0x8b, 0x52, 0x71, 0x4e, 0x85, 0x58, 0xb0, 0xaa, 0x9d, 0xdc, 0x6a, - 0xbe, 0xcd, 0x1a, 0xaf, 0x8e, 0x4f, 0xbe, 0xc8, 0xf8, 0x50, 0x66, 0xac, 0xbc, 0x2a, 0xe3, 0x43, - 0xfe, 0x61, 0xec, 0xa9, 0x1b, 0x51, 0xe8, 0x3e, 0x2a, 0xe9, 0xd8, 0x87, 0xb0, 0x22, 0xc9, 0xd5, - 0xdc, 0xb5, 0x5d, 0xd7, 0x9b, 0xbb, 0x23, 0x2a, 0x6f, 0x87, 0x13, 0x91, 0x74, 0x1c, 0xa5, 0x18, - 0x63, 0x15, 0xab, 0x85, 0xbb, 0xa1, 0xde, 0x87, 0x12, 0xe7, 0xcb, 0x39, 0xf3, 0x91, 0x4d, 0xb8, - 0x38, 0x0a, 0xb9, 0x07, 0x25, 0xce, 0x9e, 0xe7, 0xaf, 0x25, 0x36, 0x1c, 0xc1, 0x68, 0x03, 0x61, - 0x19, 0x0f, 0x69, 0xe8, 0x3b, 0xa3, 0x20, 0xba, 0x78, 0x5e, 0x0a, 0xaf, 0x66, 0xa2, 0xae, 0xc8, - 0x6e, 0x11, 0x61, 0xa2, 0x86, 0x86, 0xe3, 0xb0, 0x83, 0x69, 0x25, 0x56, 0x86, 0x60, 0x97, 0x26, - 0xb0, 0x7e, 0x42, 0xc3, 0x17, 0x94, 0xba, 0x2e, 0x63, 0x86, 0x46, 0xd4, 0x0d, 0x7d, 0x7b, 0xc2, - 0x26, 0x89, 0xf7, 0xe0, 0x51, 0xaa, 0xd4, 0x48, 0x03, 0xb8, 0x1d, 0x65, 0xdc, 0x51, 0xf9, 0x38, - 0xed, 0x58, 0x3b, 0xc9, 0x4a, 0xdb, 0xfc, 0x05, 0xd8, 0xbc, 0x3e, 0x53, 0x86, 0x9a, 0xe0, 0x5e, - 0x9c, 0xaa, 0x28, 0x2b, 0xf8, 0xc4, 0xb3, 0x43, 0xde, 0x1a, 0x9d, 0xb2, 0xf4, 0xa0, 0xa6, 0xa5, - 0x44, 0x67, 0x7f, 0x0e, 0x99, 0x3b, 0xfe, 0xc1, 0x4e, 0x24, 0xd7, 0xf3, 0xa7, 0x68, 0x75, 0x1e, - 0x5b, 0x51, 0xe9, 0x39, 0x73, 0x29, 0x82, 0xa3, 0xa3, 0x92, 0xb1, 0x05, 0x4b, 0xc8, 0xd9, 0x6b, - 0x07, 0xdd, 0xcb, 0x98, 0x41, 0x63, 0x15, 0x48, 0x8f, 0xd3, 0x2e, 0xdd, 0x25, 0xf7, 0x0f, 0x0b, - 0x50, 0xd3, 0xc0, 0xec, 0x34, 0x42, 0x3f, 0x66, 0x6b, 0xec, 0xd8, 0x53, 0x2a, 0x4d, 0xfc, 0x0d, - 0xb3, 0x81, 0xd0, 0x5d, 0x01, 0x64, 0x67, 0xb1, 0x7d, 0x71, 0x66, 0x79, 0xf3, 0xd0, 0x1a, 0xd3, - 0x33, 0x9f, 0xca, 0x56, 0xd6, 0xed, 0x8b, 0xb3, 0xfe, 0x3c, 0xdc, 0x45, 0x98, 0x0c, 0x4e, 0xa4, - 0x61, 0x15, 0x54, 0x70, 0xa2, 0x08, 0x4b, 0xf8, 0x7f, 0xf3, 0x95, 0x59, 0x54, 0xfe, 0xdf, 0x5c, - 0x5a, 0x4c, 0x1e, 0xa0, 0xa5, 0xf4, 0x01, 0xfa, 0x09, 0xac, 0xf3, 0x03, 0x54, 0x90, 0x66, 0x2b, - 0xb1, 0x93, 0x57, 0x31, 0x55, 0x74, 0x52, 0x63, 0x7b, 0x9b, 0xac, 0x07, 0x92, 0x2c, 0x05, 0xce, - 0x8f, 0x39, 0x21, 0xcb, 0x99, 0xac, 0x67, 0xa2, 0xf0, 0x81, 0xf3, 0x63, 0x2a, 0x83, 0x23, 0xc5, - 0x30, 0xc5, 0xe5, 0xbc, 0xa9, 0xe3, 0x26, 0x31, 0xed, 0xcb, 0x38, 0x66, 0x55, 0x60, 0xda, 0x97, - 0x3a, 0xe6, 0x23, 0xd8, 0x98, 0xd2, 0xb1, 0x63, 0xc7, 0x8b, 0xb5, 0x22, 0xc6, 0x6d, 0x95, 0x27, - 0x6b, 0x79, 0x06, 0x5c, 0x70, 0x67, 0xa3, 0xf1, 0x63, 0x6f, 0x7a, 0xe2, 0x70, 0x9e, 0x85, 0xbb, - 0xe0, 0x15, 0xcd, 0x45, 0x77, 0x3e, 0xfd, 0x79, 0x04, 0xb3, 0x2c, 0x81, 0xd1, 0x80, 0xda, 0x20, - 0xf4, 0x66, 0x72, 0x9a, 0x17, 0xa1, 0xce, 0x3f, 0x45, 0x60, 0x85, 0x5b, 0x70, 0x13, 0x49, 0xc2, - 0xd0, 0x9b, 0x79, 0x13, 0xef, 0xec, 0x2a, 0xa6, 0xc5, 0xfe, 0xe7, 0x39, 0x58, 0x89, 0xa5, 0x0a, - 0xf2, 0xfa, 0x09, 0xa7, 0x67, 0xea, 0x52, 0x76, 0x2e, 0x76, 0x23, 0x8f, 0xcd, 0x17, 0x47, 0xe4, - 0xc4, 0x4c, 0x5e, 0xd4, 0x6e, 0x47, 0x91, 0xc7, 0x64, 0x46, 0x4e, 0x52, 0x5a, 0x69, 0x92, 0x22, - 0xf2, 0xcb, 0x98, 0x64, 0xb2, 0x88, 0x9f, 0x11, 0x17, 0x28, 0xc7, 0xa2, 0xcb, 0x85, 0xf8, 0x15, - 0x2b, 0x5d, 0xe3, 0x2d, 0x5b, 0x10, 0xa9, 0xc1, 0x03, 0xe3, 0x77, 0xf3, 0x00, 0x51, 0xeb, 0xf0, - 0x92, 0x97, 0xe2, 0x5b, 0x72, 0xe8, 0x4d, 0xaf, 0xf1, 0x28, 0x6f, 0x41, 0x5d, 0x5d, 0xbc, 0x88, - 0x38, 0xa1, 0x9a, 0x84, 0x31, 0x76, 0xe8, 0x7d, 0x58, 0x3a, 0x9b, 0x78, 0x27, 0xc8, 0xb1, 0x0a, - 0xbe, 0x05, 0x7d, 0x68, 0xf0, 0x3c, 0x5a, 0xe4, 0x49, 0x2a, 0x76, 0xa0, 0xe2, 0x9d, 0x8a, 0x99, - 0xf7, 0x33, 0x62, 0x9c, 0xd0, 0x97, 0x29, 0x4e, 0xe8, 0x4e, 0x6a, 0x70, 0x7f, 0x3a, 0x6c, 0xd0, - 0x5f, 0xce, 0x2b, 0x5f, 0xf3, 0x68, 0x5e, 0x5e, 0x2e, 0x6c, 0xfe, 0x24, 0x9e, 0x71, 0x2f, 0x33, - 0xf5, 0x7f, 0x09, 0x8b, 0x3e, 0x3f, 0x22, 0xe5, 0xf9, 0x59, 0x7c, 0xc9, 0xf9, 0xd9, 0xf0, 0x63, - 0x7c, 0xd7, 0xb7, 0xa1, 0x69, 0x8f, 0x2f, 0xa8, 0x1f, 0x3a, 0x68, 0x39, 0x43, 0x6e, 0x5d, 0x78, - 0x76, 0x6b, 0x70, 0x64, 0x8b, 0xdf, 0x83, 0x25, 0x11, 0x7a, 0x44, 0x61, 0x8a, 0x98, 0x9c, 0x11, - 0x98, 0x21, 0x1a, 0x7f, 0x5f, 0x3a, 0xb7, 0xc7, 0xd7, 0xda, 0xcb, 0x47, 0x45, 0xef, 0x61, 0x3e, - 0xed, 0xcc, 0x20, 0x96, 0xb5, 0x30, 0xc8, 0x09, 0xea, 0xc8, 0x81, 0xc2, 0x1c, 0x17, 0x1f, 0xd6, - 0xe2, 0xeb, 0x0c, 0xab, 0xf1, 0x2f, 0x72, 0x50, 0xde, 0xf7, 0x66, 0xfb, 0x0e, 0xbf, 0x22, 0x85, - 0x9b, 0x56, 0xd9, 0x8b, 0x17, 0xd8, 0x27, 0xba, 0xf1, 0xbd, 0xe4, 0xea, 0x74, 0x26, 0xd3, 0xd9, - 0x88, 0x33, 0x9d, 0xdf, 0x83, 0x5b, 0x68, 0x8e, 0xf7, 0xbd, 0x99, 0xe7, 0x33, 0xc2, 0x61, 0x4f, - 0x38, 0xf3, 0xe9, 0xb9, 0xe1, 0xb9, 0xa4, 0xe4, 0x37, 0x4f, 0x29, 0x3d, 0xd2, 0x30, 0x0e, 0x15, - 0x02, 0x86, 0x4d, 0x98, 0x84, 0x17, 0x16, 0xd7, 0x17, 0x08, 0xee, 0x98, 0xd3, 0xf7, 0x25, 0x96, - 0xd0, 0x41, 0x38, 0xf2, 0xc7, 0xc6, 0xe7, 0x50, 0x55, 0xaa, 0x27, 0xf2, 0x3e, 0x54, 0xcf, 0xbd, - 0x99, 0xd0, 0x4f, 0xe5, 0x62, 0xd7, 0xcb, 0x45, 0xaf, 0xcd, 0xca, 0x39, 0xff, 0x11, 0x18, 0xff, - 0xa7, 0x0c, 0xe5, 0xae, 0x7b, 0xe1, 0x39, 0x23, 0x74, 0x7b, 0x9f, 0xd2, 0xa9, 0x27, 0xa3, 0x29, - 0xb1, 0xdf, 0xe8, 0x69, 0x19, 0x85, 0xcd, 0x2c, 0x08, 0x4f, 0x4b, 0x15, 0x30, 0x73, 0x0d, 0x16, - 0x7c, 0x3d, 0xee, 0x65, 0xc9, 0xc7, 0x4b, 0x45, 0xea, 0xf4, 0x2e, 0x69, 0x51, 0xb1, 0x58, 0x59, - 0xdc, 0xd3, 0x18, 0x87, 0x8c, 0x87, 0x3e, 0xa8, 0x22, 0x04, 0x07, 0xec, 0x0d, 0x28, 0x0b, 0x2d, - 0x34, 0xbf, 0x5b, 0xca, 0x75, 0xf7, 0x02, 0x84, 0xab, 0xc1, 0xa7, 0xdc, 0x9d, 0x42, 0xb1, 0xd5, - 0x05, 0xb3, 0x2e, 0x81, 0xbb, 0x36, 0xf7, 0x65, 0xe7, 0xf8, 0x1c, 0x85, 0x1f, 0x43, 0xc0, 0x41, - 0x88, 0x90, 0x11, 0x61, 0xb6, 0x9a, 0x19, 0x61, 0x16, 0xef, 0x3e, 0x28, 0x9a, 0xcf, 0xbb, 0x08, - 0x3c, 0x68, 0xa8, 0x06, 0x97, 0x01, 0x9d, 0x85, 0x86, 0x87, 0x47, 0x05, 0x91, 0x1a, 0x9e, 0xb7, - 0xa1, 0x71, 0x6a, 0x4f, 0x26, 0x27, 0xf6, 0xe8, 0x39, 0x57, 0x4c, 0xd4, 0xb9, 0x2e, 0x56, 0x02, - 0x51, 0x33, 0x71, 0x07, 0x6a, 0xda, 0x2c, 0xa3, 0x8b, 0x77, 0xd1, 0x84, 0x68, 0x7e, 0x93, 0xfa, - 0xc6, 0xc5, 0xd7, 0xd0, 0x37, 0x6a, 0xae, 0xee, 0x4b, 0x71, 0x57, 0xf7, 0x5b, 0x48, 0xdb, 0x85, - 0x03, 0x71, 0x93, 0x47, 0xa8, 0xb4, 0xc7, 0x63, 0x1e, 0xa7, 0xe7, 0x2d, 0xa8, 0x8b, 0xc1, 0xe3, - 0xe9, 0xcb, 0xe2, 0xae, 0x00, 0xc2, 0x38, 0xca, 0x6d, 0xae, 0x34, 0x9f, 0xd9, 0xce, 0x18, 0x6f, - 0x72, 0x09, 0xfb, 0x8a, 0x3d, 0x0d, 0x8f, 0x6c, 0x07, 0x5d, 0x27, 0x65, 0x32, 0x9e, 0xd5, 0x2b, - 0x7c, 0xfc, 0x45, 0xf2, 0x80, 0xc7, 0xbc, 0x51, 0x18, 0x53, 0x15, 0xd6, 0xc3, 0xac, 0x09, 0x14, - 0x5c, 0x07, 0x1f, 0xa1, 0xc7, 0x5d, 0x48, 0x31, 0x70, 0xc7, 0xa2, 0x32, 0x2f, 0x89, 0x55, 0x2a, - 0xff, 0x73, 0x43, 0x35, 0xc7, 0x64, 0xac, 0x26, 0xb7, 0x97, 0xaf, 0xc7, 0xb8, 0x71, 0x81, 0x8a, - 0xf6, 0x72, 0x8e, 0x40, 0x3e, 0xd7, 0xce, 0x90, 0x16, 0x22, 0xbf, 0x91, 0x28, 0xff, 0xba, 0xbb, - 0xb3, 0xb7, 0x01, 0x9c, 0x80, 0x9d, 0x79, 0x01, 0x75, 0xc7, 0x18, 0x7f, 0xa3, 0x62, 0x56, 0x9d, - 0xe0, 0x09, 0x07, 0xa4, 0xb4, 0x50, 0x9b, 0xe9, 0x20, 0xb8, 0xdf, 0xe8, 0x11, 0xd4, 0x86, 0xba, - 0x3e, 0x12, 0xa4, 0x02, 0xc5, 0xfe, 0x51, 0xa7, 0xd7, 0xbc, 0x41, 0x6a, 0x50, 0x1e, 0x74, 0x86, - 0xc3, 0x03, 0x34, 0xcc, 0xd7, 0xa1, 0xa2, 0x2e, 0xe0, 0xe7, 0xd9, 0x57, 0x7b, 0x67, 0xa7, 0x73, - 0x34, 0xec, 0xec, 0x36, 0x0b, 0x3f, 0x28, 0x56, 0xf2, 0xcd, 0x82, 0xf1, 0xbf, 0x0a, 0x50, 0xd3, - 0x06, 0xea, 0xe5, 0xf4, 0x3a, 0x1e, 0xea, 0x29, 0x9f, 0x0c, 0xf5, 0xa4, 0x1b, 0x55, 0x44, 0x38, - 0x2c, 0x69, 0x54, 0x79, 0x1b, 0x1a, 0x22, 0x7e, 0xa6, 0xe6, 0x5e, 0x51, 0x32, 0xeb, 0x1c, 0x28, - 0xa8, 0x39, 0x86, 0xf3, 0x40, 0x24, 0xbc, 0x28, 0x5d, 0x12, 0xeb, 0x07, 0x41, 0x78, 0x55, 0x1a, - 0xef, 0xb9, 0x07, 0xde, 0xe4, 0x82, 0x72, 0x0c, 0xce, 0xc2, 0xd6, 0x04, 0x6c, 0x28, 0x42, 0xa5, - 0x08, 0x92, 0xa9, 0xc5, 0x93, 0x28, 0x99, 0x75, 0x0e, 0x14, 0x15, 0x7d, 0x20, 0xd7, 0x18, 0x77, - 0x36, 0xdb, 0x48, 0x2f, 0x98, 0xd8, 0xfa, 0x3a, 0x48, 0xe9, 0x3d, 0xab, 0xb8, 0x76, 0xbe, 0x95, - 0xce, 0xf7, 0x6a, 0xfd, 0x27, 0x79, 0x1f, 0xc8, 0x74, 0x36, 0xb3, 0x32, 0x34, 0x92, 0x45, 0x73, - 0x69, 0x3a, 0x9b, 0x0d, 0x35, 0x85, 0x1d, 0x79, 0x03, 0x0a, 0xf6, 0x74, 0x86, 0xa4, 0x25, 0xd2, - 0x0e, 0xb6, 0x0f, 0x8f, 0x4c, 0x06, 0xfe, 0x06, 0x54, 0xa9, 0xbf, 0x99, 0x83, 0x42, 0xfb, 0xf0, - 0x08, 0x09, 0xbd, 0xe7, 0x85, 0x56, 0x70, 0x6e, 0x8b, 0x68, 0x6e, 0x8c, 0xd0, 0x7b, 0x5e, 0x38, - 0x60, 0x00, 0x46, 0xe8, 0x03, 0x1a, 0x46, 0x4e, 0xd3, 0xa5, 0x80, 0x86, 0xdc, 0x83, 0x7e, 0x74, - 0xee, 0x4c, 0xc6, 0xb1, 0x40, 0xa0, 0x80, 0x20, 0xbe, 0x22, 0x08, 0x14, 0xb5, 0xe3, 0x01, 0x7f, - 0xf3, 0x9b, 0x87, 0xe2, 0x44, 0xe1, 0x7e, 0xf9, 0xea, 0xdb, 0xf8, 0x2b, 0x39, 0x20, 0x6d, 0x46, - 0x91, 0x70, 0x40, 0x95, 0xa4, 0x1b, 0x9d, 0x33, 0x39, 0xfd, 0x9c, 0xc9, 0x20, 0xe7, 0xf9, 0x4c, - 0x72, 0xfe, 0x2a, 0xc2, 0x17, 0xdb, 0xba, 0xcb, 0xa9, 0xad, 0x6b, 0xec, 0x41, 0xed, 0x48, 0x8b, - 0xcb, 0x7c, 0x97, 0x9d, 0x8a, 0x32, 0x22, 0x33, 0x3f, 0x2f, 0xb9, 0x56, 0xd7, 0x17, 0x81, 0x98, - 0xb5, 0x06, 0xe7, 0xb5, 0x06, 0x1b, 0x7f, 0x2b, 0xc7, 0xa3, 0x13, 0xaa, 0xfe, 0x45, 0xa1, 0xa0, - 0xa5, 0x71, 0x34, 0x8a, 0x63, 0x53, 0x93, 0xe6, 0x4f, 0x11, 0x82, 0x06, 0x5b, 0x6f, 0x79, 0xa7, - 0xa7, 0x01, 0x95, 0x3e, 0x66, 0x35, 0x84, 0xf5, 0x11, 0x24, 0xc5, 0x1f, 0x26, 0x63, 0x39, 0xbc, - 0xfc, 0x40, 0x38, 0x96, 0x31, 0xf1, 0xe7, 0xd0, 0xbe, 0x14, 0xb5, 0x06, 0x6c, 0x06, 0x84, 0x85, - 0x46, 0xc6, 0x71, 0x50, 0xdf, 0xc6, 0x5f, 0x17, 0xa1, 0x76, 0x92, 0x53, 0x70, 0x1f, 0x2a, 0xaa, - 0xd4, 0x38, 0x57, 0x21, 0x31, 0x55, 0x3a, 0xe3, 0x5d, 0x50, 0x1d, 0x15, 0x6b, 0x31, 0xa7, 0x16, - 0x68, 0x65, 0xeb, 0x6a, 0xad, 0xfe, 0x0e, 0x90, 0x53, 0xc7, 0x4f, 0x22, 0x73, 0xea, 0xd1, 0xc4, - 0x14, 0x0d, 0xdb, 0x38, 0x86, 0x15, 0x49, 0xf6, 0x34, 0x99, 0x2c, 0x3e, 0xbf, 0xb9, 0x57, 0x1c, - 0x6c, 0xf9, 0xd4, 0xc1, 0x66, 0xfc, 0x46, 0x09, 0xca, 0x32, 0x0c, 0x7a, 0x56, 0x5c, 0xee, 0x6a, - 0x3c, 0x2e, 0x77, 0x2b, 0x16, 0xf5, 0x13, 0xa7, 0x5e, 0xf0, 0x38, 0xef, 0x25, 0xd9, 0x14, 0xcd, - 0x5a, 0x14, 0x63, 0x55, 0x84, 0xb5, 0xa8, 0x14, 0xb7, 0x16, 0x65, 0xc5, 0x2a, 0xe7, 0xec, 0x76, - 0x2a, 0x56, 0xf9, 0x2d, 0xe0, 0xbc, 0x93, 0xe6, 0x5c, 0x5b, 0x41, 0x80, 0x88, 0x45, 0xa2, 0xb1, - 0x5a, 0x95, 0x24, 0xab, 0xf5, 0xda, 0x6c, 0xd0, 0x27, 0xb0, 0xc0, 0xc3, 0x76, 0x89, 0xb8, 0x14, - 0xf2, 0xb0, 0x14, 0x63, 0x25, 0xff, 0xf3, 0x3b, 0x5b, 0xa6, 0xc0, 0xd5, 0x43, 0xdb, 0xd6, 0x62, - 0xa1, 0x6d, 0x75, 0x2b, 0x56, 0x3d, 0x6e, 0xc5, 0xba, 0x07, 0x4d, 0x35, 0x70, 0xa8, 0x13, 0x76, - 0x03, 0x71, 0x05, 0x7d, 0x51, 0xc2, 0x19, 0x79, 0xef, 0x05, 0xd1, 0x61, 0xbf, 0x18, 0x3b, 0xec, - 0x19, 0xf1, 0x6d, 0x87, 0x21, 0x9d, 0xce, 0x42, 0x79, 0xd8, 0x6b, 0xe1, 0xe1, 0xf9, 0xcc, 0xf3, - 0x3b, 0x6d, 0x72, 0x7a, 0xf9, 0xea, 0xd8, 0x86, 0xc5, 0x53, 0xdb, 0x99, 0xcc, 0x7d, 0x6a, 0xf9, - 0xd4, 0x0e, 0x3c, 0x17, 0xe9, 0x43, 0xc4, 0x77, 0x88, 0x2e, 0xee, 0x71, 0x1c, 0x13, 0x51, 0xcc, - 0xc6, 0xa9, 0xfe, 0x89, 0x37, 0x48, 0xf5, 0x91, 0x60, 0x67, 0xb0, 0x88, 0x4e, 0xc1, 0x7d, 0xe5, - 0xba, 0x3d, 0x6b, 0xef, 0xa0, 0xfb, 0x78, 0x7f, 0xd8, 0xcc, 0xb1, 0xcf, 0xc1, 0xf1, 0xce, 0x4e, - 0xa7, 0xb3, 0x8b, 0x67, 0x32, 0xc0, 0xc2, 0x5e, 0xbb, 0x7b, 0x20, 0x4e, 0xe4, 0x62, 0xb3, 0x64, - 0xfc, 0x61, 0x1e, 0x6a, 0x5a, 0x6f, 0x30, 0xee, 0x0c, 0xff, 0xc9, 0xe8, 0x6f, 0x59, 0xc4, 0x9d, - 0xe1, 0x90, 0xee, 0x98, 0x3c, 0x52, 0x73, 0xc4, 0xc3, 0xe5, 0xdc, 0x4e, 0x0f, 0xc8, 0x96, 0x3c, - 0xd1, 0xb4, 0x49, 0x52, 0x71, 0xe2, 0xf3, 0xd7, 0xc6, 0x89, 0x27, 0xef, 0xc2, 0x92, 0xac, 0x59, - 0xce, 0x89, 0xb0, 0xbe, 0x08, 0xb0, 0x98, 0x92, 0x77, 0x45, 0xe8, 0x1e, 0x71, 0x2c, 0x33, 0xbc, - 0xa2, 0xf4, 0x29, 0x57, 0x27, 0x33, 0x4e, 0x5d, 0x59, 0x0c, 0x9c, 0xf0, 0x96, 0x50, 0x0c, 0x8e, - 0x18, 0x4e, 0x99, 0x1c, 0x3b, 0x23, 0x16, 0x12, 0x67, 0xc4, 0xa7, 0x00, 0x51, 0x7f, 0xe2, 0xa3, - 0x7b, 0x23, 0x3e, 0xba, 0x39, 0x6d, 0x74, 0xf3, 0xc6, 0xdf, 0x13, 0x94, 0x4d, 0x4c, 0x95, 0xd2, - 0xc5, 0x7e, 0x00, 0x52, 0x3b, 0x6c, 0xe1, 0x1d, 0x94, 0xd9, 0x84, 0x86, 0xf2, 0x82, 0xfd, 0xb2, - 0x48, 0xe9, 0xaa, 0x84, 0x14, 0x25, 0xce, 0xa7, 0x29, 0xf1, 0x5b, 0x50, 0xc7, 0x58, 0x90, 0xa2, - 0x22, 0x19, 0x8c, 0x79, 0x6a, 0x5f, 0xca, 0xba, 0x63, 0x24, 0xb8, 0x98, 0x20, 0xc1, 0x7f, 0x23, - 0xc7, 0x03, 0x87, 0x45, 0x0d, 0x8d, 0x68, 0xb0, 0x2a, 0x33, 0x4e, 0x83, 0x05, 0xaa, 0xa9, 0xd2, - 0xaf, 0xa1, 0xab, 0xf9, 0x6c, 0xba, 0x9a, 0x4d, 0xb1, 0x0b, 0x99, 0x14, 0xdb, 0xb8, 0x84, 0xd6, - 0x2e, 0x65, 0x43, 0xd1, 0x9e, 0x4c, 0x92, 0x63, 0xf9, 0x00, 0x56, 0xd9, 0x14, 0xa2, 0xab, 0x08, - 0x4f, 0xd1, 0x4f, 0x34, 0xc2, 0xd3, 0x64, 0x26, 0x3c, 0xd8, 0xee, 0xc3, 0xb2, 0xc8, 0x81, 0x9b, - 0x56, 0x8f, 0xd2, 0xb6, 0xc4, 0x13, 0xd0, 0xc5, 0x95, 0xe1, 0x1a, 0xb7, 0xe0, 0x66, 0x46, 0xcd, - 0x42, 0x69, 0xf7, 0x9b, 0x39, 0x58, 0x6b, 0xf3, 0x68, 0x44, 0xdf, 0xd8, 0xfd, 0xfa, 0x2f, 0xe0, - 0xa6, 0xba, 0xae, 0xa2, 0x5d, 0xb3, 0xd5, 0x1b, 0x29, 0x6f, 0xba, 0x68, 0x97, 0xb4, 0xb0, 0xad, - 0x2d, 0x58, 0x4f, 0xb6, 0x46, 0x34, 0x74, 0x0f, 0x96, 0x77, 0xe9, 0xc9, 0xfc, 0xec, 0x80, 0x5e, - 0x44, 0x6d, 0x24, 0x50, 0x0c, 0xce, 0xbd, 0x17, 0x62, 0xa0, 0xf0, 0x37, 0xfa, 0xb3, 0x33, 0x1c, - 0x2b, 0x98, 0xd1, 0x91, 0x34, 0xfa, 0x20, 0x64, 0x30, 0xa3, 0x23, 0xe3, 0x11, 0x10, 0xbd, 0x1c, - 0xb1, 0x46, 0x98, 0x0c, 0x3c, 0x3f, 0xb1, 0x82, 0xab, 0x20, 0xa4, 0x53, 0x79, 0xd5, 0x1c, 0x82, - 0xf9, 0xc9, 0x80, 0x43, 0x8c, 0xf7, 0xa0, 0x7e, 0x64, 0x5f, 0x99, 0xf4, 0x47, 0xe2, 0xb6, 0xf6, - 0x06, 0x94, 0x67, 0xf6, 0x15, 0x3b, 0x08, 0x94, 0xfd, 0x17, 0x93, 0x8d, 0xdf, 0x2d, 0xc2, 0x02, - 0xc7, 0x24, 0x77, 0xf9, 0x13, 0x32, 0x8e, 0x8b, 0x84, 0x58, 0x1e, 0x89, 0x1a, 0x28, 0x75, 0x6a, - 0xe6, 0xd3, 0xa7, 0xa6, 0x50, 0x56, 0xcb, 0x50, 0x97, 0xd2, 0x52, 0xe7, 0xce, 0xa7, 0x32, 0xbe, - 0x65, 0x3c, 0xf6, 0x4e, 0x31, 0x7a, 0x94, 0x88, 0xc7, 0x1d, 0x89, 0xfb, 0x52, 0x44, 0x92, 0x36, - 0x6f, 0x9d, 0x64, 0x06, 0xc4, 0x81, 0xa9, 0x83, 0x32, 0xc5, 0xf9, 0xb2, 0x0c, 0x65, 0x10, 0x17, - 0xe7, 0x53, 0x62, 0x7b, 0xe5, 0xd5, 0x62, 0x3b, 0xd7, 0x62, 0xbf, 0x44, 0x6c, 0x87, 0xd7, 0x10, - 0xdb, 0x5f, 0xc3, 0x8f, 0xe1, 0x26, 0x54, 0x90, 0xc3, 0xd3, 0xce, 0x4f, 0xc6, 0xd9, 0xb1, 0xf3, - 0xf3, 0x33, 0x4d, 0xb0, 0xe5, 0x4e, 0x54, 0xda, 0x01, 0x66, 0xd2, 0x1f, 0xfd, 0x74, 0x14, 0xa3, - 0xcf, 0xa0, 0x2c, 0xa0, 0x6c, 0x41, 0xbb, 0xf6, 0x54, 0x06, 0x74, 0xc6, 0xdf, 0x6c, 0xd8, 0x30, - 0xc4, 0xe9, 0x8f, 0xe6, 0x8e, 0x4f, 0xc7, 0x32, 0xd0, 0xa2, 0x83, 0xd4, 0x83, 0x41, 0x58, 0x07, - 0x99, 0x90, 0xed, 0xca, 0xd7, 0x23, 0x2a, 0x66, 0xd9, 0x09, 0x9e, 0xb0, 0x4f, 0x83, 0x40, 0x13, - 0xc3, 0xe7, 0xcf, 0x3c, 0x5f, 0xb2, 0x27, 0xc6, 0xef, 0xe5, 0xa0, 0x29, 0x76, 0x97, 0x4a, 0xd3, - 0x05, 0xd8, 0xd2, 0x75, 0x3e, 0x3f, 0x2f, 0x0f, 0x9b, 0x68, 0x40, 0x03, 0x55, 0x7b, 0x8a, 0x57, - 0xe1, 0xaa, 0xc9, 0x1a, 0x03, 0xee, 0x09, 0x7e, 0xe5, 0x4d, 0xa8, 0xc9, 0xdb, 0x36, 0x53, 0x67, - 0x22, 0xdf, 0x1f, 0xe3, 0xd7, 0x6d, 0x0e, 0x9d, 0x89, 0x64, 0x75, 0x7c, 0x5b, 0x84, 0xd7, 0xc8, - 0x21, 0xab, 0x63, 0xda, 0x21, 0x35, 0xfe, 0x20, 0x07, 0xcb, 0x5a, 0x57, 0xc4, 0xbe, 0xfd, 0x2e, - 0xd4, 0xd5, 0xab, 0x1e, 0x54, 0xf1, 0xd8, 0x1b, 0x71, 0x1a, 0x15, 0x65, 0xab, 0x8d, 0x14, 0x24, - 0x60, 0x8d, 0x19, 0xdb, 0x57, 0xfc, 0x4a, 0xc8, 0x7c, 0x2a, 0xe5, 0xf2, 0xb1, 0x7d, 0xb5, 0x47, - 0xe9, 0x60, 0x3e, 0x25, 0x77, 0xa1, 0xfe, 0x82, 0xd2, 0xe7, 0x0a, 0x81, 0x13, 0x76, 0x60, 0x30, - 0x81, 0x61, 0x40, 0x63, 0xea, 0xb9, 0xe1, 0xb9, 0x42, 0x11, 0xf2, 0x05, 0x02, 0x39, 0x8e, 0xf1, - 0xaf, 0xf2, 0xb0, 0xc2, 0x15, 0xc8, 0xc2, 0x8c, 0x20, 0x48, 0x57, 0x0b, 0x16, 0xb8, 0x56, 0x9f, - 0x13, 0xaf, 0xfd, 0x1b, 0xa6, 0xf8, 0x26, 0x9f, 0xbc, 0xa6, 0xd2, 0x5b, 0x46, 0xe6, 0xb8, 0x66, - 0xf8, 0x0b, 0xe9, 0xe1, 0xbf, 0x7e, 0x78, 0xb3, 0x9c, 0x0a, 0x4a, 0x59, 0x4e, 0x05, 0xaf, 0x63, - 0xca, 0x4f, 0xc5, 0x86, 0x28, 0xa7, 0x63, 0x34, 0x3f, 0x82, 0x8d, 0x18, 0x0e, 0x52, 0x6b, 0xe7, - 0xd4, 0x51, 0x8f, 0x0b, 0xac, 0x6a, 0xd8, 0x03, 0x99, 0xb6, 0x5d, 0x86, 0x52, 0x30, 0xf2, 0x66, - 0xe8, 0x87, 0x1e, 0x1f, 0x55, 0x71, 0x4c, 0xfc, 0x76, 0x0e, 0x5a, 0x7b, 0x51, 0xb0, 0x6b, 0x27, - 0x08, 0x3d, 0x5f, 0xbd, 0xdb, 0x70, 0x1b, 0x80, 0xbf, 0x85, 0x86, 0x6a, 0x10, 0x11, 0xa5, 0x0c, - 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, 0xb7, 0xc3, 0x46, 0x87, 0x5e, 0x20, 0xb3, - 0x51, 0x54, 0xf1, 0x76, 0x0e, 0xed, 0x4b, 0xbc, 0x4e, 0x10, 0x18, 0xff, 0x20, 0x0f, 0x4b, 0x51, - 0xfb, 0x78, 0xc4, 0xb1, 0xbb, 0xa9, 0xd8, 0x69, 0xc2, 0x1f, 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, 0x96, 0xae, 0x72, 0x94, 0xfe, 0x3c, 0x64, 0xe2, 0xb5, 0x3d, 0x65, 0xdc, 0x8a, - 0x10, 0x70, 0x4b, 0xf6, 0x34, 0xec, 0xe2, 0xa3, 0x7b, 0x0c, 0xcc, 0xb2, 0xf1, 0xc9, 0x64, 0x58, - 0x0c, 0xbf, 0xc9, 0xa5, 0x2d, 0x3e, 0x7b, 0x28, 0x69, 0xe9, 0xa2, 0x08, 0x7f, 0xea, 0x47, 0x89, - 0x22, 0x6f, 0x42, 0x8d, 0x17, 0x1e, 0x85, 0x03, 0xc1, 0x40, 0x8f, 0x61, 0xd7, 0xc5, 0x74, 0xa1, - 0xe6, 0xf4, 0xe6, 0x31, 0xcd, 0x0d, 0xf0, 0xaa, 0xe4, 0xfb, 0x68, 0xaa, 0xc7, 0x96, 0x32, 0x42, - 0xd6, 0x14, 0xac, 0x17, 0x30, 0x6e, 0xe5, 0x66, 0xc6, 0xec, 0x0a, 0x62, 0xb0, 0x03, 0x5a, 0x64, - 0x74, 0x39, 0x09, 0x9c, 0x22, 0xac, 0x4b, 0xea, 0x1b, 0x1f, 0x7a, 0xb3, 0x79, 0x1a, 0x07, 0x44, - 0x52, 0x38, 0x9f, 0xe8, 0x58, 0xdc, 0x1a, 0xe4, 0xe9, 0xf8, 0x6c, 0x73, 0x01, 0xf8, 0x08, 0x36, - 0x3b, 0x97, 0x8c, 0xb0, 0x28, 0xc7, 0xfa, 0xd1, 0xf3, 0xb9, 0xb4, 0x8f, 0x26, 0xac, 0x2c, 0xb9, - 0xd7, 0xb2, 0xb2, 0x8c, 0x79, 0xb4, 0x08, 0x55, 0xd6, 0x4f, 0x52, 0x08, 0xd7, 0x2f, 0xd9, 0xae, - 0x75, 0x82, 0x45, 0xc8, 0xe0, 0x34, 0x0c, 0xc4, 0x0b, 0x35, 0x02, 0x58, 0x3a, 0x9c, 0x4f, 0x42, - 0x67, 0x47, 0x81, 0xc8, 0x27, 0x22, 0x0f, 0xd6, 0x23, 0x47, 0x2d, 0xb3, 0x22, 0x50, 0x15, 0xe1, - 0x60, 0x4d, 0x59, 0x41, 0x56, 0xba, 0xbe, 0xa5, 0x69, 0xbc, 0x06, 0xe3, 0x26, 0x6c, 0x44, 0x5f, - 0x7c, 0xd8, 0xe4, 0x89, 0xf4, 0x37, 0x73, 0xfc, 0x8a, 0x13, 0x4f, 0x1b, 0xb8, 0xf6, 0x2c, 0x38, - 0xf7, 0x42, 0xd2, 0x81, 0x95, 0xc0, 0x71, 0xcf, 0x26, 0x54, 0x2f, 0x3e, 0x10, 0x83, 0xb0, 0x16, - 0x6f, 0x1b, 0xcf, 0x1a, 0x98, 0xcb, 0x3c, 0x47, 0x54, 0x5a, 0x40, 0xb6, 0xaf, 0x6b, 0x64, 0xb4, - 0x2c, 0x12, 0xa3, 0x91, 0x6e, 0x7c, 0x17, 0x16, 0xe3, 0x15, 0x91, 0xcf, 0x44, 0x90, 0x95, 0xa8, - 0x55, 0x85, 0x44, 0x88, 0x89, 0x68, 0x41, 0xd4, 0xa2, 0xb1, 0x0f, 0x8c, 0xbf, 0x94, 0x83, 0x96, - 0x49, 0xd9, 0xca, 0xd5, 0x5a, 0x29, 0xd7, 0xcc, 0x77, 0x53, 0xa5, 0x5e, 0xdf, 0x57, 0x19, 0xbb, - 0x45, 0xb6, 0xe8, 0x3b, 0xd7, 0x4e, 0xc6, 0xfe, 0x8d, 0x54, 0x8f, 0xb6, 0x2b, 0xb0, 0xc0, 0x51, - 0x8c, 0x0d, 0x58, 0x13, 0xed, 0x91, 0x6d, 0x89, 0x0c, 0xfa, 0xb1, 0x1a, 0x63, 0x06, 0xfd, 0x4d, - 0x68, 0xf1, 0x58, 0x08, 0x7a, 0x27, 0x44, 0xc6, 0x5d, 0x20, 0x87, 0xf6, 0xc8, 0xf6, 0x3d, 0xcf, - 0x3d, 0xa2, 0xbe, 0x70, 0x99, 0x47, 0x46, 0x14, 0xed, 0xdd, 0x92, 0x63, 0xe6, 0x5f, 0x32, 0xe8, - 0xbe, 0xe7, 0x4a, 0x0f, 0x41, 0xfe, 0x65, 0xf8, 0xb0, 0xb2, 0x6d, 0x3f, 0xa7, 0xb2, 0x24, 0x39, - 0x44, 0x5f, 0x42, 0x6d, 0xa6, 0x0a, 0x95, 0xe3, 0x2e, 0xe3, 0x57, 0xa5, 0xab, 0x35, 0x75, 0x6c, - 0x46, 0xa5, 0x50, 0x61, 0x8b, 0x11, 0x61, 0xc6, 0xf2, 0xcc, 0x67, 0xa0, 0x27, 0xf4, 0xaa, 0x3b, - 0x36, 0x1e, 0xc2, 0x6a, 0xbc, 0x4e, 0x41, 0x5a, 0x36, 0xa1, 0x32, 0x15, 0x30, 0xd1, 0x7a, 0xf5, - 0xcd, 0x64, 0x16, 0x26, 0x77, 0xca, 0x3c, 0xdd, 0x5d, 0x15, 0xd6, 0xe0, 0x4b, 0xd8, 0x48, 0xa5, - 0x88, 0x02, 0xef, 0x42, 0x5d, 0x6b, 0x08, 0xef, 0x46, 0xd1, 0x04, 0xd5, 0x92, 0xc0, 0xf8, 0x02, - 0x36, 0xb8, 0xd8, 0x16, 0x65, 0x97, 0x43, 0x90, 0xe8, 0x45, 0x2e, 0xd9, 0x8b, 0x4f, 0xa4, 0xac, - 0xa9, 0x67, 0x8d, 0xe2, 0x47, 0x8e, 0x31, 0x4d, 0x3a, 0x79, 0xc9, 0x4f, 0xe3, 0x18, 0xd6, 0xd3, - 0xc3, 0xc7, 0xda, 0xff, 0x67, 0x1a, 0x72, 0x39, 0x3c, 0x51, 0xb2, 0x1a, 0x9e, 0xff, 0x9c, 0xe3, - 0xe3, 0x13, 0x4b, 0x12, 0xcd, 0x1c, 0x03, 0x99, 0xd2, 0xf0, 0xdc, 0x1b, 0x5b, 0xe9, 0x9a, 0x1f, - 0x29, 0x1f, 0xb3, 0xcc, 0xbc, 0x5b, 0x87, 0x98, 0x51, 0x4b, 0x11, 0xb7, 0x1d, 0xa6, 0x49, 0xf8, - 0xe6, 0x08, 0xd6, 0xb3, 0x91, 0x33, 0x3c, 0xb3, 0x3e, 0x8e, 0xf3, 0xf3, 0xb7, 0xaf, 0xed, 0x3e, - 0x6b, 0x96, 0xce, 0xde, 0xff, 0x6e, 0x05, 0xca, 0x42, 0x55, 0x43, 0xb6, 0xa0, 0x38, 0x92, 0x5e, - 0xbe, 0x51, 0x0c, 0x51, 0x91, 0x2a, 0xff, 0xef, 0xa0, 0xaf, 0x2f, 0xc3, 0x23, 0x5f, 0xc2, 0x62, - 0xdc, 0xd1, 0x25, 0x11, 0xeb, 0x27, 0xee, 0xa1, 0xd2, 0x18, 0x25, 0x9c, 0x08, 0xaa, 0x11, 0x0f, - 0xc6, 0x59, 0xd3, 0xca, 0xb9, 0xc6, 0xa4, 0x79, 0x2e, 0x13, 0xeb, 0x82, 0x73, 0xdb, 0x7a, 0xf8, - 0xe8, 0x53, 0x61, 0x54, 0xa8, 0x21, 0x70, 0x70, 0x6e, 0x3f, 0x7c, 0xf4, 0x69, 0x52, 0x60, 0x13, - 0xa1, 0x7e, 0x34, 0x81, 0x6d, 0x15, 0x4a, 0xfc, 0x65, 0x02, 0xee, 0xae, 0xc9, 0x3f, 0xa4, 0x3a, - 0x63, 0xee, 0x53, 0x4b, 0x5c, 0xac, 0xe1, 0xa7, 0x28, 0x7f, 0x45, 0x8e, 0x88, 0xb4, 0x01, 0x26, - 0x71, 0x75, 0xe2, 0x3a, 0x2c, 0x9c, 0x47, 0x4f, 0x4d, 0x34, 0x4c, 0xf1, 0x65, 0xfc, 0x8f, 0x12, - 0xd4, 0xb4, 0x41, 0x21, 0x75, 0xa8, 0x98, 0x9d, 0x41, 0xc7, 0x7c, 0xda, 0xd9, 0x6d, 0xde, 0x20, - 0xf7, 0xe0, 0x9d, 0x6e, 0x6f, 0xa7, 0x6f, 0x9a, 0x9d, 0x9d, 0xa1, 0xd5, 0x37, 0x2d, 0x19, 0xda, - 0xf6, 0xa8, 0xfd, 0xec, 0xb0, 0xd3, 0x1b, 0x5a, 0xbb, 0x9d, 0x61, 0xbb, 0x7b, 0x30, 0x68, 0xe6, - 0xc8, 0x1b, 0xd0, 0x8a, 0x30, 0x65, 0x72, 0xfb, 0xb0, 0x7f, 0xdc, 0x1b, 0x36, 0xf3, 0xe4, 0x0e, - 0xdc, 0xda, 0xeb, 0xf6, 0xda, 0x07, 0x56, 0x84, 0xb3, 0x73, 0x30, 0x7c, 0x6a, 0x75, 0x7e, 0xee, - 0xa8, 0x6b, 0x3e, 0x6b, 0x16, 0xb2, 0x10, 0xf6, 0x87, 0x07, 0x3b, 0xb2, 0x84, 0x22, 0xb9, 0x09, - 0x6b, 0x1c, 0x81, 0x67, 0xb1, 0x86, 0xfd, 0xbe, 0x35, 0xe8, 0xf7, 0x7b, 0xcd, 0x12, 0x59, 0x86, - 0x46, 0xb7, 0xf7, 0xb4, 0x7d, 0xd0, 0xdd, 0xb5, 0xcc, 0x4e, 0xfb, 0xe0, 0xb0, 0xb9, 0x40, 0x56, - 0x60, 0x29, 0x89, 0x57, 0x66, 0x45, 0x48, 0xbc, 0x7e, 0xaf, 0xdb, 0xef, 0x59, 0x4f, 0x3b, 0xe6, - 0xa0, 0xdb, 0xef, 0x35, 0x2b, 0x64, 0x1d, 0x48, 0x3c, 0x69, 0xff, 0xb0, 0xbd, 0xd3, 0xac, 0x92, - 0x35, 0x58, 0x8e, 0xc3, 0x9f, 0x74, 0x9e, 0x35, 0x81, 0xb4, 0x60, 0x95, 0x37, 0xcc, 0xda, 0xee, - 0x1c, 0xf4, 0xbf, 0xb2, 0x0e, 0xbb, 0xbd, 0xee, 0xe1, 0xf1, 0x61, 0xb3, 0x86, 0x01, 0xc6, 0x3b, - 0x1d, 0xab, 0xdb, 0x1b, 0x1c, 0xef, 0xed, 0x75, 0x77, 0xba, 0x9d, 0xde, 0xb0, 0x59, 0xe7, 0x35, - 0x67, 0x75, 0xbc, 0xc1, 0x32, 0x88, 0xbb, 0xa7, 0xd6, 0x6e, 0x77, 0xd0, 0xde, 0x3e, 0xe8, 0xec, - 0x36, 0x17, 0xc9, 0x6d, 0xb8, 0x39, 0xec, 0x1c, 0x1e, 0xf5, 0xcd, 0xb6, 0xf9, 0x4c, 0xde, 0x4d, - 0xb5, 0xf6, 0xda, 0xdd, 0x83, 0x63, 0xb3, 0xd3, 0x5c, 0x22, 0x6f, 0xc1, 0x6d, 0xb3, 0xf3, 0xc3, - 0xe3, 0xae, 0xd9, 0xd9, 0xb5, 0x7a, 0xfd, 0xdd, 0x8e, 0xb5, 0xd7, 0x69, 0x0f, 0x8f, 0xcd, 0x8e, - 0x75, 0xd8, 0x1d, 0x0c, 0xba, 0xbd, 0xc7, 0xcd, 0x26, 0x79, 0x07, 0xee, 0x2a, 0x14, 0x55, 0x40, - 0x02, 0x6b, 0x99, 0xf5, 0x4f, 0x4e, 0x69, 0xaf, 0xf3, 0x73, 0x43, 0xeb, 0xa8, 0xd3, 0x31, 0x9b, - 0x84, 0x6c, 0xc2, 0x7a, 0x54, 0x3d, 0xaf, 0x40, 0xd4, 0xbd, 0xc2, 0xd2, 0x8e, 0x3a, 0xe6, 0x61, - 0xbb, 0xc7, 0x26, 0x38, 0x96, 0xb6, 0xca, 0x9a, 0x1d, 0xa5, 0x25, 0x9b, 0xbd, 0x46, 0x08, 0x2c, - 0x6a, 0xb3, 0xb2, 0xd7, 0x36, 0x9b, 0xeb, 0x64, 0x09, 0x6a, 0x87, 0x47, 0x47, 0xd6, 0xb0, 0x7b, - 0xd8, 0xe9, 0x1f, 0x0f, 0x9b, 0x1b, 0xe9, 0x59, 0x3a, 0x6a, 0x3f, 0x3b, 0xe8, 0xb7, 0x77, 0x9b, - 0x2d, 0xb2, 0x06, 0xcd, 0x6e, 0x6f, 0xd8, 0x31, 0xd9, 0x32, 0x90, 0xa5, 0xfe, 0x97, 0x32, 0x59, - 0x85, 0x25, 0xd9, 0x09, 0x09, 0xfd, 0xa3, 0x32, 0xd9, 0x00, 0x72, 0xdc, 0x33, 0x3b, 0xed, 0x5d, - 0x36, 0xa6, 0x2a, 0xe1, 0xbf, 0x96, 0x85, 0x79, 0xf9, 0xf7, 0x0a, 0x8a, 0x0f, 0x8c, 0x1c, 0xcc, - 0xe2, 0xcf, 0x46, 0xd5, 0xb5, 0xe7, 0x9e, 0x5e, 0xf5, 0xb4, 0xa8, 0x26, 0xdc, 0x17, 0x52, 0xc2, - 0x7d, 0x4a, 0x7b, 0xd4, 0xd0, 0x25, 0x8f, 0xb7, 0xa1, 0x31, 0xe5, 0x4f, 0x48, 0x89, 0x37, 0x48, - 0x40, 0x78, 0x5b, 0x72, 0x20, 0x7f, 0x80, 0x24, 0xf5, 0xb6, 0x66, 0x29, 0xfd, 0xb6, 0x66, 0x96, - 0x84, 0xb9, 0x90, 0x25, 0x61, 0xde, 0x87, 0x65, 0x4e, 0xb5, 0x1c, 0xd7, 0x99, 0x4a, 0xbd, 0x8d, - 0x78, 0xa9, 0x12, 0xa9, 0x17, 0x87, 0x4b, 0x81, 0x56, 0x0a, 0xbd, 0x82, 0xba, 0x94, 0x85, 0xbc, - 0x1b, 0x93, 0x75, 0x39, 0x51, 0x51, 0xb2, 0xae, 0xaa, 0xc1, 0xbe, 0x8c, 0x6a, 0xa8, 0x69, 0x35, - 0x70, 0x38, 0xd6, 0x70, 0x1f, 0x96, 0xe9, 0x65, 0xe8, 0xdb, 0x96, 0x37, 0xb3, 0x7f, 0x34, 0x47, - 0x17, 0x19, 0x1b, 0xb5, 0x48, 0x75, 0x73, 0x09, 0x13, 0xfa, 0x08, 0xdf, 0xb5, 0x43, 0xdb, 0xf8, - 0x45, 0x00, 0x75, 0xe0, 0xe2, 0x8b, 0x9f, 0xae, 0x27, 0xef, 0xd4, 0xd6, 0x4d, 0xfe, 0x81, 0xf3, - 0x18, 0x7a, 0xbe, 0x7d, 0x46, 0xbb, 0xd2, 0x2a, 0x1c, 0x01, 0xc8, 0x2d, 0x28, 0x78, 0x33, 0xe9, - 0x8b, 0x58, 0x95, 0x41, 0xf5, 0x67, 0x26, 0x83, 0x1a, 0x9f, 0x42, 0xbe, 0x3f, 0xbb, 0x96, 0x8b, - 0xc2, 0x07, 0xce, 0xf8, 0xab, 0x06, 0x79, 0xf4, 0x3f, 0x94, 0x9f, 0xf7, 0xff, 0x3c, 0xd4, 0xb4, - 0xf7, 0xd0, 0xc8, 0x06, 0xac, 0x7c, 0xd5, 0x1d, 0xf6, 0x3a, 0x83, 0x81, 0x75, 0x74, 0xbc, 0xfd, - 0xa4, 0xf3, 0xcc, 0xda, 0x6f, 0x0f, 0xf6, 0x9b, 0x37, 0x18, 0x99, 0xe9, 0x75, 0x06, 0xc3, 0xce, - 0x6e, 0x0c, 0x9e, 0x23, 0x6f, 0xc2, 0xe6, 0x71, 0xef, 0x78, 0xd0, 0xd9, 0xb5, 0xb2, 0xf2, 0xe5, - 0xd9, 0xbe, 0x12, 0xe9, 0x19, 0xd9, 0x0b, 0xf7, 0x7f, 0x09, 0x16, 0xe3, 0x81, 0x65, 0x08, 0xc0, - 0xc2, 0x41, 0xe7, 0x71, 0x7b, 0xe7, 0x19, 0x7f, 0x34, 0x61, 0x30, 0x6c, 0x0f, 0xbb, 0x3b, 0x96, - 0x78, 0x24, 0x81, 0xd1, 0xb0, 0x1c, 0xa9, 0x41, 0xb9, 0xdd, 0xdb, 0xd9, 0xef, 0x9b, 0x83, 0x66, - 0x9e, 0xbc, 0x01, 0x1b, 0x72, 0x0b, 0xed, 0xf4, 0x0f, 0x0f, 0xbb, 0x43, 0x24, 0xdf, 0xc3, 0x67, - 0x47, 0x6c, 0xc7, 0xdc, 0xb7, 0xa1, 0x1a, 0xbd, 0xef, 0x80, 0x24, 0xb1, 0x3b, 0xec, 0xb6, 0x87, - 0xd1, 0x79, 0xd0, 0xbc, 0xc1, 0x28, 0x6e, 0x04, 0xc6, 0x47, 0x1a, 0x9a, 0x39, 0x7e, 0xf7, 0x5e, - 0x02, 0x79, 0xed, 0xcd, 0x3c, 0x23, 0x03, 0x11, 0x74, 0xbb, 0x3f, 0x64, 0x5d, 0xf8, 0x65, 0x58, - 0x8c, 0x3f, 0xa3, 0x40, 0x9a, 0x50, 0x67, 0xf5, 0x6b, 0x55, 0x00, 0x2c, 0xf0, 0x16, 0x37, 0x73, - 0x9c, 0xe6, 0xef, 0xf4, 0x0f, 0xbb, 0xbd, 0xc7, 0x78, 0x50, 0x34, 0xf3, 0x0c, 0xd4, 0x3f, 0x1e, - 0x3e, 0xee, 0x2b, 0x50, 0x81, 0xe5, 0xe0, 0xdd, 0x69, 0x16, 0xef, 0xff, 0x08, 0x96, 0x53, 0x0f, - 0x2e, 0xb0, 0x56, 0xf7, 0x8f, 0x87, 0x3b, 0xfd, 0x43, 0xbd, 0x9e, 0x1a, 0x94, 0x77, 0x0e, 0xda, - 0xdd, 0x43, 0x34, 0xd4, 0x34, 0xa0, 0x7a, 0xdc, 0x93, 0x9f, 0xf9, 0xf8, 0x53, 0x11, 0x05, 0x46, - 0xbd, 0xf6, 0xba, 0xe6, 0x60, 0x68, 0x0d, 0x86, 0xed, 0xc7, 0x9d, 0x66, 0x91, 0xe5, 0x95, 0xa4, - 0xac, 0x74, 0xff, 0x0b, 0x58, 0x8c, 0x3b, 0xce, 0xc7, 0xed, 0x6f, 0x9b, 0xb0, 0xbe, 0xdd, 0x19, - 0x7e, 0xd5, 0xe9, 0xf4, 0x70, 0xca, 0x77, 0x3a, 0xbd, 0xa1, 0xd9, 0x3e, 0xe8, 0x0e, 0x9f, 0x35, - 0x73, 0xf7, 0xbf, 0x84, 0x66, 0xd2, 0xe9, 0x23, 0xe6, 0x25, 0xf3, 0x32, 0x77, 0x9a, 0xfb, 0xff, - 0x36, 0x07, 0xab, 0x59, 0xe6, 0x41, 0xb6, 0x30, 0x05, 0x21, 0x64, 0x27, 0xe5, 0xa0, 0xdf, 0xb3, - 0x7a, 0x7d, 0x0c, 0x95, 0xbe, 0x09, 0xeb, 0x89, 0x04, 0xd9, 0x8b, 0x1c, 0xb9, 0x05, 0x1b, 0xa9, - 0x4c, 0x96, 0xd9, 0x3f, 0xc6, 0xb9, 0x6c, 0xc1, 0x6a, 0x22, 0xb1, 0x63, 0x9a, 0x7d, 0xb3, 0x59, - 0x20, 0xdf, 0x81, 0x7b, 0x89, 0x94, 0x34, 0x7f, 0x20, 0xd9, 0x87, 0x22, 0x79, 0x0f, 0xde, 0x4e, - 0x61, 0x47, 0x47, 0xa8, 0xb5, 0xdd, 0x3e, 0x60, 0xdd, 0x6b, 0x96, 0xee, 0xff, 0x41, 0x11, 0x20, - 0xba, 0x99, 0xca, 0xea, 0xdf, 0x6d, 0x0f, 0xdb, 0x07, 0x7d, 0xb6, 0x67, 0xcc, 0xfe, 0x90, 0x95, - 0x6e, 0x76, 0x7e, 0xd8, 0xbc, 0x91, 0x99, 0xd2, 0x3f, 0x62, 0x1d, 0xda, 0x80, 0x15, 0xbe, 0xfe, - 0x0e, 0x58, 0x37, 0xd8, 0x72, 0xe1, 0x51, 0xf7, 0x19, 0x13, 0x72, 0x7c, 0xb4, 0x67, 0xf6, 0x7b, - 0x43, 0x6b, 0xb0, 0x7f, 0x3c, 0xdc, 0xc5, 0x20, 0xfe, 0x3b, 0x66, 0xf7, 0x88, 0x97, 0x59, 0x7c, - 0x19, 0x02, 0x2b, 0xba, 0xc4, 0x36, 0xf8, 0xe3, 0xfe, 0x60, 0xd0, 0x3d, 0xb2, 0x7e, 0x78, 0xdc, - 0x31, 0xbb, 0x9d, 0x01, 0x66, 0x5c, 0xc8, 0x80, 0x33, 0xfc, 0x32, 0x5b, 0xb3, 0xc3, 0x83, 0xa7, - 0xe2, 0xa0, 0x63, 0xa8, 0x95, 0x38, 0x88, 0x61, 0x55, 0xd9, 0xec, 0xb0, 0xc3, 0x39, 0xa3, 0x64, - 0xb8, 0x26, 0x8d, 0xe5, 0xab, 0xb1, 0xa3, 0x34, 0xb5, 0xf3, 0x31, 0x5b, 0x3d, 0x3b, 0x89, 0xe5, - 0x42, 0x8e, 0x44, 0xf1, 0x6f, 0xbb, 0xbb, 0x26, 0x66, 0x58, 0x4c, 0x41, 0x19, 0xee, 0x12, 0x5b, - 0x84, 0xec, 0xf4, 0x66, 0x28, 0x4d, 0xf9, 0xc1, 0x52, 0x96, 0x59, 0x8f, 0xbf, 0x3a, 0x3e, 0xdc, - 0xee, 0x4b, 0x36, 0x80, 0xb7, 0x97, 0x64, 0xc0, 0x19, 0xfe, 0x0a, 0xbe, 0x92, 0xc0, 0xc9, 0x11, - 0x22, 0xae, 0xea, 0x00, 0x86, 0xb1, 0xc6, 0x88, 0xa0, 0x04, 0xfc, 0x7c, 0xc7, 0xec, 0x5b, 0x8c, - 0xcf, 0x42, 0x1e, 0x91, 0xe1, 0xaf, 0x5f, 0x9f, 0xcc, 0x72, 0x6f, 0x3c, 0xfc, 0xa7, 0x6f, 0x41, - 0x55, 0xdd, 0x98, 0x21, 0x3f, 0x80, 0x46, 0x2c, 0x20, 0x05, 0xb9, 0x95, 0x1d, 0xa6, 0x02, 0xa5, - 0xa8, 0xcd, 0x37, 0x5e, 0x16, 0xc3, 0x82, 0x1c, 0x6a, 0x8a, 0x0b, 0x5e, 0xd8, 0x1b, 0x49, 0x65, - 0x42, 0xac, 0xb4, 0xdb, 0xd7, 0xa4, 0x8a, 0xe2, 0x9e, 0xe0, 0x83, 0x04, 0x18, 0xc0, 0x51, 0x1c, - 0x2f, 0xe4, 0x76, 0x14, 0x1d, 0x5e, 0x87, 0xcb, 0x02, 0xa5, 0x98, 0xa8, 0xa5, 0xed, 0xd2, 0xd0, - 0x76, 0x26, 0x01, 0xd9, 0x85, 0x9a, 0xf6, 0xc6, 0x2f, 0xb9, 0x79, 0xed, 0x83, 0xc4, 0x9b, 0x9b, - 0x59, 0x49, 0xa2, 0x49, 0xdf, 0x83, 0xaa, 0x7a, 0xe3, 0x94, 0x6c, 0x68, 0x6f, 0xf0, 0xea, 0x6f, - 0xc3, 0x6e, 0xb6, 0xd2, 0x09, 0x22, 0xff, 0x2e, 0xd4, 0xb4, 0x07, 0x49, 0x55, 0x2b, 0xd2, 0xcf, - 0xa1, 0xaa, 0x56, 0x64, 0xbd, 0x5f, 0x7a, 0x00, 0x6b, 0x42, 0x3d, 0x72, 0x42, 0xbf, 0xce, 0xf0, - 0x90, 0xf4, 0xf0, 0x3c, 0xc8, 0x91, 0x2f, 0xa1, 0x22, 0x9f, 0xc1, 0x25, 0xeb, 0xd9, 0xcf, 0x0a, - 0x6f, 0x6e, 0xa4, 0xe0, 0xa2, 0x29, 0x6d, 0x80, 0xe8, 0x41, 0x53, 0x22, 0x3b, 0x9e, 0x7a, 0x3a, - 0x55, 0xcd, 0x4c, 0xc6, 0xeb, 0xa7, 0xbb, 0x50, 0xd3, 0xde, 0x2e, 0x55, 0x63, 0x92, 0x7e, 0xf7, - 0x54, 0x8d, 0x49, 0xd6, 0x53, 0xa7, 0x3f, 0x80, 0x46, 0xec, 0x11, 0x52, 0xb5, 0x8e, 0xb3, 0x9e, - 0x38, 0x55, 0xeb, 0x38, 0xfb, 0xdd, 0xd2, 0x5d, 0xa8, 0x69, 0x0f, 0x83, 0xaa, 0x16, 0xa5, 0x5f, - 0x27, 0x55, 0x2d, 0xca, 0x78, 0x47, 0x94, 0xed, 0x86, 0xf8, 0xab, 0xa0, 0x6a, 0x37, 0x64, 0x3e, - 0x2f, 0xaa, 0x76, 0x43, 0xf6, 0x53, 0xa2, 0x6c, 0xe9, 0xa9, 0x97, 0x48, 0xc8, 0x46, 0x4c, 0x2b, - 0x11, 0x3d, 0x69, 0xa2, 0x96, 0x5e, 0xfa, 0xd1, 0x92, 0xc7, 0xb0, 0xa2, 0x16, 0x8d, 0x7a, 0x47, - 0x24, 0x50, 0x6d, 0xca, 0x7c, 0xad, 0x64, 0xb3, 0x99, 0x4c, 0x7d, 0x90, 0x23, 0x9f, 0x43, 0x59, - 0x3c, 0xce, 0x40, 0xd6, 0x92, 0x8f, 0x35, 0xf0, 0x46, 0xac, 0x67, 0xbf, 0xe1, 0x40, 0x8e, 0x70, - 0x43, 0xeb, 0xaf, 0x27, 0xe8, 0x2b, 0x36, 0xe3, 0xc1, 0x85, 0xcd, 0x37, 0xaf, 0x4b, 0x8e, 0x4a, - 0x4c, 0xbe, 0xf8, 0x71, 0xfb, 0xba, 0xc0, 0x5a, 0xf1, 0x12, 0xaf, 0x8b, 0x00, 0xfa, 0x18, 0xea, - 0xfa, 0x8b, 0x70, 0x44, 0xdf, 0x87, 0xc9, 0xb2, 0x6e, 0x65, 0xa6, 0x89, 0x82, 0x9e, 0xc2, 0xba, - 0x1a, 0x6f, 0x3d, 0xca, 0x53, 0x40, 0xee, 0x64, 0xc4, 0x7e, 0x8a, 0x8d, 0xfa, 0xcd, 0x6b, 0x83, - 0x43, 0x3d, 0xc8, 0x21, 0x91, 0x8d, 0x3d, 0xe2, 0x14, 0x11, 0xd9, 0xac, 0xb7, 0xab, 0x22, 0x22, - 0x9b, 0xfd, 0xf2, 0x53, 0x1b, 0x96, 0xb4, 0x28, 0x55, 0x83, 0x2b, 0x77, 0xa4, 0xd6, 0x7b, 0x3a, - 0x5c, 0xfd, 0x66, 0x96, 0x92, 0x9e, 0xec, 0x40, 0x4d, 0x0f, 0x74, 0xf5, 0x92, 0xec, 0x1b, 0x5a, - 0x92, 0x1e, 0x45, 0xfc, 0x41, 0x8e, 0x1c, 0x40, 0x33, 0x19, 0x96, 0x56, 0x6d, 0xe1, 0xac, 0x50, - 0xbe, 0x9b, 0x89, 0xc4, 0x58, 0x30, 0x5b, 0xb6, 0x2e, 0x44, 0xd5, 0xfc, 0xfd, 0x55, 0xcf, 0x4f, - 0x1e, 0x45, 0x1c, 0x2e, 0x87, 0x41, 0x95, 0x96, 0x48, 0xc5, 0x66, 0xdf, 0xcb, 0x3d, 0xc8, 0x91, - 0x3d, 0xa8, 0xc7, 0xa2, 0x32, 0xc6, 0x2e, 0x6f, 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, 0x17, 0xf3, 0x39, 0xec, 0xd7, 0x77, 0xf9, 0x8b, 0xf3, 0xd2, 0x39, 0x8e, 0xcd, 0xff, - 0xeb, 0x16, 0x42, 0xf6, 0x78, 0xe5, 0x43, 0x8f, 0xc7, 0x64, 0xb8, 0xa9, 0xe1, 0x08, 0xd8, 0xeb, - 0xb5, 0xa1, 0xcd, 0xdb, 0x20, 0xf2, 0xc4, 0xd6, 0xe0, 0x6b, 0x96, 0x45, 0x3e, 0x03, 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, 0xc7, 0xd0, 0x38, 0xf0, 0xbc, 0xe7, - 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, 0xdc, 0x18, 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, 0x3d, 0x85, 0xe5, 0x94, 0xb3, 0x97, 0xa2, 0x6e, 0xd7, 0x39, 0xa0, 0x6d, 0xde, - 0xbd, 0x1e, 0x41, 0x94, 0xfb, 0x7d, 0x68, 0xf0, 0xa0, 0xf2, 0x27, 0x94, 0xdf, 0xfb, 0x4e, 0x84, - 0x0c, 0xd4, 0x2f, 0x95, 0x27, 0x49, 0x12, 0xcf, 0xf0, 0x18, 0x9f, 0xb7, 0xd2, 0x6e, 0x55, 0xab, - 0x79, 0x4d, 0xdf, 0xf4, 0x56, 0xf3, 0x9a, 0x75, 0x81, 0xfb, 0x0b, 0xa8, 0x3d, 0xa6, 0xa1, 0xbc, - 0xa7, 0xac, 0xf8, 0xa3, 0xc4, 0xc5, 0xe5, 0xcd, 0x8c, 0xdb, 0xe5, 0xe4, 0x53, 0xcc, 0xaa, 0x62, - 0x6e, 0xac, 0x6b, 0xb5, 0xe8, 0x59, 0x97, 0x12, 0x70, 0xc6, 0x7d, 0x68, 0x91, 0x77, 0x54, 0xc3, - 0xd3, 0x91, 0x96, 0x54, 0xc3, 0xb3, 0x02, 0xf5, 0xfc, 0x2c, 0x1f, 0x01, 0xed, 0x66, 0x74, 0xc4, - 0x82, 0x25, 0x2f, 0x51, 0xab, 0xe6, 0xeb, 0xe8, 0x8f, 0x00, 0x06, 0xa1, 0x37, 0xdb, 0xb5, 0xe9, - 0xd4, 0x73, 0x23, 0x9a, 0x10, 0xdd, 0xc9, 0x8d, 0x36, 0xa2, 0x76, 0x31, 0x97, 0x7c, 0xa5, 0xf1, - 0xa6, 0xb1, 0x29, 0x91, 0xd3, 0x7e, 0xed, 0xb5, 0x5d, 0xd5, 0x9d, 0x8c, 0xab, 0xbb, 0x48, 0x24, - 0x20, 0xf2, 0xa5, 0x53, 0x9c, 0x66, 0xca, 0x4d, 0x4f, 0xed, 0xf5, 0x0c, 0xc7, 0xbb, 0xef, 0x41, - 0x35, 0x72, 0x42, 0xda, 0x88, 0xc2, 0x80, 0xc5, 0x5c, 0x96, 0x14, 0xf5, 0x4e, 0x3b, 0x00, 0xf5, - 0x60, 0x85, 0x37, 0x47, 0x1d, 0x7f, 0x78, 0x57, 0x53, 0xbd, 0xce, 0x96, 0xf6, 0xbc, 0x51, 0xfb, - 0x27, 0xcb, 0x7f, 0x84, 0xed, 0x9f, 0x94, 0x83, 0x81, 0xda, 0x3f, 0xd7, 0x39, 0x96, 0xa8, 0xfd, - 0x73, 0xbd, 0x6f, 0x42, 0x0f, 0x56, 0x32, 0x5c, 0x05, 0xc8, 0x5b, 0x52, 0xb0, 0xb9, 0xd6, 0x8d, - 0x60, 0x33, 0xd3, 0xa4, 0x4c, 0x86, 0xb0, 0xc1, 0xf3, 0xb4, 0x27, 0x93, 0x84, 0x65, 0xfa, 0x4d, - 0x2d, 0x43, 0x86, 0xb5, 0x3d, 0xc6, 0xca, 0x24, 0x2c, 0xee, 0x3d, 0x68, 0x26, 0x8d, 0xba, 0xe4, - 0x7a, 0xf4, 0xcd, 0x3b, 0x31, 0x96, 0x3d, 0x6d, 0x08, 0x26, 0x4f, 0x95, 0x69, 0x39, 0xd1, 0xc6, - 0x3b, 0xd1, 0x2b, 0xa3, 0x99, 0x86, 0x70, 0x25, 0x0d, 0x64, 0x5a, 0xa6, 0xc9, 0xcf, 0xc1, 0x46, - 0x72, 0x45, 0xcb, 0x92, 0xef, 0x66, 0x0d, 0xd7, 0xb5, 0xac, 0x5c, 0xbc, 0x43, 0x0f, 0x72, 0x8c, - 0x10, 0xeb, 0x06, 0x60, 0xb5, 0x90, 0x32, 0x2c, 0xd1, 0x6a, 0x21, 0x65, 0x5a, 0x8c, 0x8f, 0x60, - 0x29, 0x61, 0xfb, 0x55, 0x6c, 0x70, 0xb6, 0xb5, 0x58, 0xb1, 0xc1, 0xd7, 0x99, 0x8c, 0x07, 0xd0, - 0x4c, 0x5a, 0x75, 0xd5, 0x5c, 0x5f, 0x63, 0x29, 0xde, 0xbc, 0x73, 0x6d, 0x7a, 0xbc, 0x99, 0x9a, - 0xfd, 0x33, 0xd6, 0xcc, 0xb4, 0xd5, 0x36, 0xd6, 0xcc, 0x0c, 0xeb, 0xeb, 0xf6, 0x7b, 0x3f, 0xff, - 0xad, 0x33, 0x27, 0x3c, 0x9f, 0x9f, 0x6c, 0x8d, 0xbc, 0xe9, 0x87, 0x13, 0xa9, 0xd5, 0x10, 0x81, - 0x14, 0x3e, 0x9c, 0xb8, 0xe3, 0x0f, 0xb1, 0x80, 0x93, 0x85, 0x99, 0xef, 0x85, 0xde, 0xc7, 0xff, - 0x37, 0x00, 0x00, 0xff, 0xff, 0xe1, 0xea, 0x86, 0x7c, 0x00, 0x95, 0x00, 0x00, + // 12707 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7d, 0x5b, 0x6c, 0x23, 0x59, + 0x76, 0x58, 0xf3, 0x25, 0x92, 0x87, 0xa4, 0x44, 0x5d, 0xbd, 0xd8, 0xea, 0xe9, 0xe9, 0x9e, 0x9a, + 0xd9, 0x99, 0xde, 0x9e, 0x19, 0x4d, 0x4f, 0xcf, 0xf4, 0x3c, 0x76, 0xe2, 0xf5, 0x52, 0x12, 0xd5, + 0xe2, 0xb6, 0x44, 0x6a, 0x8b, 0xd4, 0x8c, 0xdb, 0xb0, 0x5d, 0x2e, 0x91, 0x57, 0x52, 0xa5, 0xc9, + 0x2a, 0x6e, 0x55, 0x51, 0x2d, 0x6d, 0x10, 0xc0, 0x1f, 0x8e, 0x1d, 0x18, 0x4e, 0x80, 0x00, 0x71, + 0x80, 0x20, 0x31, 0x92, 0x20, 0x41, 0xf2, 0x67, 0x18, 0xb0, 0xfd, 0x95, 0x7c, 0xe4, 0x2b, 0x41, + 0x80, 0x04, 0x41, 0x80, 0x18, 0x79, 0x7c, 0x24, 0x08, 0x90, 0x38, 0x40, 0x0c, 0x24, 0x06, 0xfc, + 0x99, 0x04, 0x09, 0xee, 0xb9, 0x8f, 0xba, 0xf5, 0x50, 0x77, 0xcf, 0xee, 0x78, 0x7f, 0x24, 0xd6, + 0xb9, 0xe7, 0xbe, 0xef, 0x3d, 0xf7, 0xbc, 0xee, 0xb9, 0x50, 0xf5, 0x67, 0xa3, 0xad, 0x99, 0xef, + 0x85, 0x1e, 0x29, 0x4d, 0x5c, 0x7f, 0x36, 0x32, 0xfe, 0x28, 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, 0x68, 0x5b, 0x6d, 0x9e, 0x34, 0xbc, 0x9a, 0x51, 0xb3, 0x66, 0x47, + 0x1f, 0xa4, 0x05, 0x65, 0xf1, 0xd9, 0xca, 0xdf, 0xcd, 0xdd, 0xab, 0x9a, 0xf2, 0x93, 0xdc, 0x06, + 0xb0, 0xa7, 0xde, 0xdc, 0x0d, 0xad, 0xc0, 0x0e, 0x5b, 0x85, 0xbb, 0xb9, 0x7b, 0x05, 0xb3, 0xca, + 0x21, 0x03, 0x3b, 0x24, 0xb7, 0xa0, 0x3a, 0x7b, 0x66, 0x05, 0x23, 0xdf, 0x99, 0x85, 0xad, 0x22, + 0x66, 0xad, 0xcc, 0x9e, 0x0d, 0xf0, 0x9b, 0xbc, 0x0b, 0x15, 0x6f, 0x1e, 0xce, 0x3c, 0xc7, 0x0d, + 0x5b, 0xa5, 0xbb, 0xb9, 0x7b, 0xb5, 0x87, 0x4b, 0xa2, 0x21, 0xfd, 0x79, 0x78, 0xc4, 0xc0, 0xa6, + 0x42, 0x20, 0x6f, 0x41, 0x63, 0xe4, 0xb9, 0xa7, 0x8e, 0x3f, 0xb5, 0x43, 0xc7, 0x73, 0x83, 0xd6, + 0x02, 0xd6, 0x15, 0x07, 0x1a, 0xff, 0x2c, 0x0f, 0xb5, 0xa1, 0x6f, 0xbb, 0x81, 0x3d, 0x62, 0x00, + 0xb2, 0x01, 0xe5, 0xf0, 0xd2, 0x3a, 0xb7, 0x83, 0x73, 0xec, 0x6a, 0xd5, 0x5c, 0x08, 0x2f, 0xf7, + 0xed, 0xe0, 0x9c, 0xac, 0xc3, 0x02, 0x6f, 0x25, 0x76, 0xa8, 0x60, 0x8a, 0x2f, 0xf2, 0x2e, 0x2c, + 0xbb, 0xf3, 0xa9, 0x15, 0xaf, 0x8a, 0x75, 0xab, 0x64, 0x36, 0xdd, 0xf9, 0x74, 0x47, 0x87, 0xb3, + 0xce, 0x9f, 0x4c, 0xbc, 0xd1, 0x33, 0x5e, 0x01, 0xef, 0x5e, 0x15, 0x21, 0x58, 0xc7, 0x1b, 0x50, + 0x17, 0xc9, 0xd4, 0x39, 0x3b, 0xe7, 0x7d, 0x2c, 0x99, 0x35, 0x8e, 0x80, 0x20, 0x56, 0x42, 0xe8, + 0x4c, 0xa9, 0x15, 0x84, 0xf6, 0x74, 0x26, 0xba, 0x54, 0x65, 0x90, 0x01, 0x03, 0x60, 0xb2, 0x17, + 0xda, 0x13, 0xeb, 0x94, 0xd2, 0xa0, 0x55, 0x16, 0xc9, 0x0c, 0xb2, 0x47, 0x69, 0x40, 0xbe, 0x05, + 0x8b, 0x63, 0x1a, 0x84, 0x96, 0x98, 0x0c, 0x1a, 0xb4, 0x2a, 0x77, 0x0b, 0xf7, 0xaa, 0x66, 0x83, + 0x41, 0xdb, 0x12, 0x48, 0x5e, 0x03, 0xf0, 0xed, 0xe7, 0x16, 0x1b, 0x08, 0x7a, 0xd9, 0xaa, 0xf2, + 0x59, 0xf0, 0xed, 0xe7, 0xc3, 0xcb, 0x7d, 0x7a, 0x49, 0x56, 0xa1, 0x34, 0xb1, 0x4f, 0xe8, 0xa4, + 0x05, 0x98, 0xc0, 0x3f, 0x8c, 0x10, 0xd6, 0x1f, 0xd3, 0x50, 0x1b, 0xca, 0xc0, 0xa4, 0x3f, 0x9c, + 0xd3, 0x20, 0x64, 0xbd, 0x0a, 0x42, 0xdb, 0x0f, 0x65, 0xaf, 0x72, 0xbc, 0x57, 0x08, 0x8b, 0x7a, + 0x45, 0xdd, 0xb1, 0x44, 0xc8, 0x23, 0x42, 0x95, 0xba, 0x63, 0x91, 0xcc, 0x56, 0xd3, 0x68, 0x84, + 0x83, 0x5f, 0x10, 0xab, 0x89, 0x7f, 0x1a, 0x07, 0x40, 0xb4, 0x2a, 0x77, 0x69, 0x68, 0x3b, 0x93, + 0x80, 0x7c, 0x02, 0xf5, 0x50, 0x6b, 0x48, 0x2b, 0x77, 0xb7, 0x70, 0xaf, 0xa6, 0x16, 0xad, 0x96, + 0xc1, 0x8c, 0xe1, 0x19, 0xe7, 0x50, 0xd9, 0xa3, 0xf4, 0xc0, 0x99, 0x3a, 0x21, 0x59, 0x87, 0xd2, + 0xa9, 0x73, 0x49, 0xc7, 0xd8, 0xdc, 0xc2, 0xfe, 0x0d, 0x93, 0x7f, 0x92, 0x3b, 0x00, 0xf8, 0xc3, + 0x9a, 0xaa, 0xf5, 0xbb, 0x7f, 0xc3, 0xac, 0x22, 0xec, 0x30, 0xb0, 0x43, 0xb2, 0x09, 0xe5, 0x19, + 0xf5, 0x47, 0x54, 0xae, 0x94, 0xfd, 0x1b, 0xa6, 0x04, 0x6c, 0x97, 0xa1, 0x34, 0x61, 0xa5, 0x1b, + 0xff, 0xa3, 0x04, 0xb5, 0x01, 0x75, 0xc7, 0x72, 0x8c, 0x08, 0x14, 0xd9, 0x14, 0x60, 0x65, 0x75, + 0x13, 0x7f, 0x93, 0x37, 0xa1, 0x86, 0x93, 0x15, 0x84, 0xbe, 0xe3, 0x9e, 0xf1, 0x7d, 0xb4, 0x9d, + 0x6f, 0xe5, 0x4c, 0x60, 0xe0, 0x01, 0x42, 0x49, 0x13, 0x0a, 0xf6, 0x54, 0xee, 0x23, 0xf6, 0x93, + 0xdc, 0x84, 0x8a, 0x3d, 0x0d, 0x79, 0xf3, 0xea, 0x08, 0x2e, 0xdb, 0xd3, 0x10, 0x9b, 0xf6, 0x06, + 0xd4, 0x67, 0xf6, 0xd5, 0x94, 0xba, 0x61, 0xb4, 0x00, 0xeb, 0x66, 0x4d, 0xc0, 0x70, 0x09, 0x3e, + 0x84, 0x15, 0x1d, 0x45, 0x56, 0x5e, 0x52, 0x95, 0x2f, 0x6b, 0xd8, 0xa2, 0x0d, 0xef, 0xc0, 0x92, + 0xcc, 0xe3, 0xf3, 0xfe, 0xe0, 0xc2, 0xac, 0x9a, 0x8b, 0x02, 0x2c, 0x7b, 0x79, 0x0f, 0x9a, 0xa7, + 0x8e, 0x6b, 0x4f, 0xac, 0xd1, 0x24, 0xbc, 0xb0, 0xc6, 0x74, 0x12, 0xda, 0xb8, 0x46, 0x4b, 0xe6, + 0x22, 0xc2, 0x77, 0x26, 0xe1, 0xc5, 0x2e, 0x83, 0x92, 0xf7, 0xa0, 0x7a, 0x4a, 0xa9, 0x85, 0x83, + 0xd5, 0xaa, 0xc4, 0xb6, 0xba, 0x9c, 0x21, 0xb3, 0x72, 0x2a, 0xe7, 0xea, 0x3d, 0x68, 0x7a, 0xf3, + 0xf0, 0xcc, 0x73, 0xdc, 0x33, 0x6b, 0x74, 0x6e, 0xbb, 0x96, 0x33, 0xc6, 0x55, 0x5b, 0xdc, 0xce, + 0x3f, 0xc8, 0x99, 0x8b, 0x32, 0x6d, 0xe7, 0xdc, 0x76, 0xbb, 0x63, 0xf2, 0x36, 0x2c, 0x4d, 0xec, + 0x20, 0xb4, 0xce, 0xbd, 0x99, 0x35, 0x9b, 0x9f, 0x3c, 0xa3, 0x57, 0xad, 0x06, 0x0e, 0x44, 0x83, + 0x81, 0xf7, 0xbd, 0xd9, 0x11, 0x02, 0xd9, 0xa2, 0xc4, 0x76, 0xf2, 0x46, 0xb0, 0xc5, 0xde, 0x30, + 0xab, 0x0c, 0xc2, 0x2b, 0x7d, 0x0a, 0x2b, 0x38, 0x3d, 0xa3, 0x79, 0x10, 0x7a, 0x53, 0xcb, 0xa7, + 0x23, 0xcf, 0x1f, 0x07, 0xad, 0x1a, 0xae, 0xb5, 0x6f, 0x8b, 0xc6, 0x6a, 0x73, 0xbc, 0xb5, 0x4b, + 0x83, 0x70, 0x07, 0x91, 0x4d, 0x8e, 0xdb, 0x71, 0x43, 0xff, 0xca, 0x5c, 0x1e, 0x27, 0xe1, 0xe4, + 0x3d, 0x20, 0xf6, 0x64, 0xe2, 0x3d, 0xb7, 0x02, 0x3a, 0x39, 0xb5, 0xc4, 0x20, 0xb6, 0x16, 0xef, + 0xe6, 0xee, 0x55, 0xcc, 0x26, 0xa6, 0x0c, 0xe8, 0xe4, 0xf4, 0x88, 0xc3, 0xc9, 0x27, 0x80, 0xdb, + 0xd7, 0x3a, 0xa5, 0x76, 0x38, 0xf7, 0x69, 0xd0, 0x5a, 0xba, 0x5b, 0xb8, 0xb7, 0xf8, 0x70, 0x59, + 0x8d, 0x17, 0x82, 0xb7, 0x9d, 0xd0, 0xac, 0x33, 0x3c, 0xf1, 0x1d, 0xe8, 0xab, 0x81, 0xd1, 0x83, + 0x56, 0x33, 0xb6, 0x1a, 0x18, 0x35, 0xd8, 0xdc, 0x85, 0xf5, 0xec, 0x56, 0xb3, 0x75, 0xc7, 0x06, + 0x8e, 0xad, 0xd7, 0xa2, 0xc9, 0x7e, 0x32, 0xb2, 0x70, 0x61, 0x4f, 0xe6, 0x14, 0x17, 0x6a, 0xdd, + 0xe4, 0x1f, 0xdf, 0xc9, 0x7f, 0x96, 0x33, 0x7e, 0x3f, 0x07, 0x75, 0x3e, 0x10, 0xc1, 0xcc, 0x73, + 0x03, 0x4a, 0xde, 0x84, 0x86, 0xac, 0x99, 0xfa, 0xbe, 0xe7, 0x0b, 0x52, 0x2b, 0x9b, 0xd3, 0x61, + 0x30, 0xf2, 0x6d, 0x68, 0x4a, 0xa4, 0x99, 0x4f, 0x9d, 0xa9, 0x7d, 0x26, 0x8b, 0x96, 0xab, 0xed, + 0x48, 0x80, 0xc9, 0x87, 0x51, 0x79, 0xbe, 0x37, 0x0f, 0x29, 0x6e, 0x87, 0xda, 0xc3, 0xba, 0x18, + 0x01, 0x93, 0xc1, 0x54, 0xe9, 0xf8, 0xf5, 0x0a, 0x5b, 0xc1, 0xf8, 0xad, 0x1c, 0x10, 0xd6, 0xec, + 0xa1, 0xc7, 0x0b, 0x88, 0xc8, 0x59, 0x2c, 0x67, 0xee, 0x95, 0x37, 0x51, 0xfe, 0x45, 0x9b, 0xc8, + 0x80, 0x12, 0x6f, 0x7b, 0x31, 0xa3, 0xed, 0x3c, 0xe9, 0xfb, 0xc5, 0x4a, 0xa1, 0x59, 0x34, 0xfe, + 0x63, 0x01, 0x56, 0xd9, 0x52, 0x76, 0xe9, 0xa4, 0x3d, 0x1a, 0xd1, 0x99, 0xda, 0x5e, 0x77, 0xa0, + 0xe6, 0x7a, 0x63, 0x2a, 0x17, 0x35, 0x6f, 0x18, 0x30, 0x90, 0xb6, 0xa2, 0xcf, 0x6d, 0xc7, 0xe5, + 0x0d, 0xe7, 0x83, 0x59, 0x45, 0x08, 0x36, 0xfb, 0x6d, 0x58, 0x9a, 0x51, 0x77, 0xac, 0xef, 0xa2, + 0x02, 0xdf, 0x18, 0x02, 0x2c, 0x36, 0xd0, 0x1d, 0xa8, 0x9d, 0xce, 0x39, 0x1e, 0xa3, 0x3d, 0x45, + 0x5c, 0x03, 0x20, 0x40, 0x6d, 0x4e, 0x82, 0x66, 0xf3, 0xe0, 0x1c, 0x53, 0x4b, 0x98, 0x5a, 0x66, + 0xdf, 0x2c, 0xe9, 0x36, 0xc0, 0x78, 0x1e, 0x84, 0x62, 0x53, 0x2d, 0x60, 0x62, 0x95, 0x41, 0xf8, + 0xa6, 0x7a, 0x1f, 0x56, 0xa6, 0xf6, 0xa5, 0x85, 0x6b, 0xc7, 0x72, 0x5c, 0xeb, 0x74, 0x82, 0x27, + 0x42, 0x19, 0xf1, 0x9a, 0x53, 0xfb, 0xf2, 0x4b, 0x96, 0xd2, 0x75, 0xf7, 0x10, 0xce, 0x28, 0xcf, + 0x88, 0x8f, 0x84, 0xe5, 0xd3, 0x80, 0xfa, 0x17, 0x14, 0x89, 0x45, 0xd1, 0x5c, 0x14, 0x60, 0x93, + 0x43, 0x59, 0x8b, 0xa6, 0xac, 0xdf, 0xe1, 0x64, 0xc4, 0x29, 0x83, 0x59, 0x9e, 0x3a, 0xee, 0x7e, + 0x38, 0x19, 0xb1, 0xc3, 0x8e, 0x91, 0x9a, 0x19, 0xf5, 0xad, 0x67, 0xcf, 0x71, 0x9b, 0x17, 0x91, + 0xb4, 0x1c, 0x51, 0xff, 0xc9, 0x73, 0xc6, 0x8f, 0x8c, 0x02, 0xa4, 0x55, 0xf6, 0x55, 0xab, 0x86, + 0x34, 0xa0, 0x32, 0x0a, 0x18, 0x95, 0xb2, 0xaf, 0xd8, 0x3e, 0x65, 0xad, 0xb5, 0x71, 0x16, 0xe8, + 0x18, 0x8b, 0x0f, 0x90, 0xe8, 0x36, 0xb0, 0xb1, 0x6d, 0x91, 0xc0, 0xea, 0x09, 0xd8, 0xaa, 0x97, + 0x8d, 0x3d, 0x9d, 0xd8, 0x67, 0x01, 0x52, 0x9d, 0x86, 0x59, 0x17, 0xc0, 0x3d, 0x06, 0x33, 0xfe, + 0x34, 0x0f, 0x6b, 0x89, 0xc9, 0x15, 0x9b, 0x86, 0x31, 0x20, 0x08, 0xc1, 0x89, 0xad, 0x98, 0xe2, + 0x2b, 0x6b, 0xd6, 0xf2, 0x59, 0xb3, 0xb6, 0x0a, 0x25, 0xbe, 0xd9, 0xf8, 0x11, 0xca, 0x3f, 0xd8, + 0x2e, 0x9b, 0xcf, 0x4e, 0x7d, 0x8f, 0xf1, 0x63, 0xe7, 0xf3, 0x70, 0xec, 0x3d, 0x77, 0x05, 0x5f, + 0xb2, 0x24, 0xe0, 0x03, 0x01, 0x8e, 0x0f, 0x45, 0x29, 0x31, 0x14, 0x77, 0xa0, 0x26, 0x66, 0x00, + 0xf9, 0x3a, 0x3e, 0xb1, 0x20, 0x40, 0x8c, 0xb1, 0x7b, 0x17, 0x88, 0x9a, 0x4f, 0x8b, 0x8d, 0x1a, + 0x1e, 0x50, 0x7c, 0x62, 0x97, 0x1c, 0x31, 0xa1, 0x87, 0xf6, 0x25, 0x1e, 0x54, 0x6f, 0xc1, 0x22, + 0x43, 0x61, 0xe3, 0x69, 0xf1, 0x73, 0xbf, 0xc2, 0xc7, 0x6a, 0x6a, 0x5f, 0xb2, 0xc1, 0xdc, 0x41, + 0xd6, 0xeb, 0x75, 0xa8, 0xc9, 0x49, 0xb5, 0x1c, 0x57, 0xcc, 0x6b, 0x55, 0xcc, 0x6b, 0xd7, 0x65, + 0xc7, 0x0d, 0x4b, 0xe7, 0xe3, 0x64, 0x8d, 0xe9, 0x2c, 0x3c, 0x17, 0x64, 0x7c, 0x71, 0xea, 0xb8, + 0x7c, 0x78, 0x77, 0x19, 0xd4, 0xf8, 0xed, 0x1c, 0xd4, 0xc5, 0xa8, 0x23, 0x1b, 0x49, 0xb6, 0x80, + 0xc8, 0x25, 0x1e, 0x5e, 0x3a, 0x63, 0xeb, 0xe4, 0x2a, 0xa4, 0x01, 0xdf, 0x51, 0xfb, 0x37, 0xcc, + 0xa6, 0x48, 0x1b, 0x5e, 0x3a, 0xe3, 0x6d, 0x96, 0x42, 0xee, 0x43, 0x33, 0x86, 0x1f, 0x84, 0x3e, + 0xdf, 0xee, 0xfb, 0x37, 0xcc, 0x45, 0x0d, 0x7b, 0x10, 0xfa, 0x8c, 0x80, 0x30, 0x26, 0x75, 0x1e, + 0x5a, 0x8e, 0x3b, 0xa6, 0x97, 0x38, 0x1f, 0x0d, 0xb3, 0xc6, 0x61, 0x5d, 0x06, 0xda, 0x5e, 0x84, + 0xba, 0x5e, 0x9c, 0x71, 0x06, 0x15, 0xc9, 0xe1, 0x22, 0x8b, 0x97, 0x68, 0x92, 0x59, 0x0d, 0x55, + 0x4b, 0x6e, 0x42, 0x25, 0xde, 0x02, 0xb3, 0x1c, 0xbe, 0x72, 0xc5, 0xc6, 0x77, 0xa1, 0x79, 0xc0, + 0x26, 0xc2, 0x65, 0x3b, 0x59, 0x70, 0xec, 0xeb, 0xb0, 0xa0, 0x51, 0x94, 0xaa, 0x29, 0xbe, 0x18, + 0xcf, 0x72, 0xee, 0x05, 0xa1, 0xa8, 0x05, 0x7f, 0x1b, 0xff, 0x3c, 0x07, 0xa4, 0x13, 0x84, 0xce, + 0xd4, 0x0e, 0xe9, 0x1e, 0x55, 0x34, 0xb3, 0x0f, 0x75, 0x56, 0xda, 0xd0, 0x6b, 0x73, 0x16, 0x9a, + 0x33, 0x64, 0xef, 0x0a, 0x1a, 0x97, 0xce, 0xb0, 0xa5, 0x63, 0xf3, 0x63, 0x32, 0x56, 0x00, 0x5b, + 0x6e, 0xa1, 0xed, 0x9f, 0xd1, 0x10, 0x19, 0x6f, 0xc1, 0x31, 0x02, 0x07, 0x31, 0x96, 0x7b, 0xf3, + 0x67, 0x61, 0x39, 0x55, 0x86, 0x7e, 0x68, 0x55, 0x33, 0x0e, 0xad, 0x82, 0x7e, 0x68, 0xfd, 0x7a, + 0x0e, 0x56, 0x62, 0x0d, 0x13, 0xdb, 0x70, 0x03, 0xca, 0x8c, 0x5c, 0xb0, 0xc5, 0x9b, 0xe3, 0x82, + 0xc0, 0x29, 0xc5, 0x05, 0xfe, 0x11, 0xac, 0x9e, 0x52, 0xea, 0xdb, 0x21, 0x26, 0x22, 0x3d, 0x61, + 0x53, 0xc4, 0x4b, 0xe6, 0x54, 0x5f, 0xa4, 0x0f, 0xec, 0xf0, 0x88, 0xfa, 0x6c, 0xba, 0x88, 0x01, + 0x0d, 0x89, 0x7c, 0x81, 0xd8, 0x05, 0x5c, 0xc4, 0xb5, 0x00, 0x51, 0xbe, 0x64, 0x20, 0xe3, 0x8f, + 0xf3, 0xb0, 0xc4, 0xce, 0xa1, 0x43, 0xdb, 0xbd, 0x92, 0x03, 0x7a, 0x90, 0x39, 0xa0, 0xf7, 0x34, + 0xae, 0x43, 0xc3, 0xfe, 0xba, 0xa3, 0x59, 0x48, 0x8e, 0x66, 0xba, 0x99, 0xc5, 0x54, 0x33, 0xc9, + 0x5b, 0x50, 0x8f, 0xf5, 0xbb, 0xa4, 0xfa, 0x0d, 0x41, 0xd4, 0x61, 0x25, 0x3c, 0x2c, 0x68, 0xc2, + 0x03, 0x23, 0x2d, 0x6c, 0xa7, 0xb2, 0xda, 0x03, 0xc1, 0x11, 0x32, 0x7a, 0xcd, 0xea, 0x0e, 0x98, + 0x84, 0x15, 0x30, 0x52, 0x66, 0xcd, 0x5d, 0x21, 0x65, 0xd1, 0x31, 0xd2, 0x83, 0x8a, 0xd9, 0xc4, + 0x84, 0xe3, 0x08, 0xfe, 0x93, 0xcf, 0xfb, 0xdb, 0xd0, 0x8c, 0x86, 0x4f, 0xcc, 0x39, 0x81, 0x22, + 0xdb, 0x43, 0xa2, 0x00, 0xfc, 0x6d, 0xfc, 0x83, 0x3c, 0x47, 0xdc, 0xf1, 0x9c, 0x48, 0xd4, 0x21, + 0x50, 0x44, 0x56, 0x4a, 0x20, 0xb2, 0xdf, 0xd7, 0x0a, 0x8e, 0x3f, 0xc5, 0x41, 0xbf, 0x09, 0x95, + 0x80, 0x0d, 0xa0, 0x3d, 0xe1, 0xe3, 0x5e, 0x31, 0xcb, 0xec, 0xbb, 0x3d, 0x99, 0x44, 0xf3, 0x51, + 0xbe, 0x76, 0x3e, 0x2a, 0xaf, 0x32, 0x1f, 0xd5, 0xec, 0xf9, 0x30, 0xde, 0x81, 0x65, 0x6d, 0x94, + 0x5e, 0x30, 0x9e, 0xe7, 0x40, 0x0e, 0x9c, 0x20, 0x3c, 0x76, 0x59, 0x11, 0x8a, 0xa5, 0x89, 0x35, + 0x24, 0x97, 0x68, 0x08, 0x4b, 0xb4, 0x2f, 0x45, 0x62, 0x5e, 0x24, 0xda, 0x97, 0x3c, 0xf1, 0x7a, + 0x99, 0xf1, 0x33, 0x58, 0x89, 0xd5, 0x24, 0x1a, 0xf5, 0x06, 0x94, 0xe6, 0xe1, 0xa5, 0x27, 0xa5, + 0xc5, 0x9a, 0xd8, 0x4b, 0xc7, 0xe1, 0xa5, 0x67, 0xf2, 0x14, 0xe3, 0x18, 0x96, 0x7b, 0xf4, 0xb9, + 0xa0, 0x8b, 0xb2, 0x89, 0x6f, 0x43, 0xf1, 0x25, 0x9a, 0x11, 0x4c, 0xd7, 0x1b, 0x94, 0x8f, 0x37, + 0x68, 0x0b, 0x88, 0x5e, 0xac, 0x68, 0x8f, 0xa6, 0x42, 0xc9, 0xc5, 0x54, 0x28, 0xc6, 0xdb, 0x40, + 0x06, 0xce, 0x99, 0x7b, 0x48, 0x83, 0xc0, 0x3e, 0x53, 0x34, 0xb6, 0x09, 0x85, 0x69, 0x70, 0x26, + 0x0e, 0x04, 0xf6, 0xd3, 0xf8, 0x08, 0x56, 0x62, 0x78, 0xa2, 0xe0, 0xd7, 0xa0, 0x1a, 0x38, 0x67, + 0x2e, 0x4a, 0x01, 0xa2, 0xe8, 0x08, 0x60, 0xec, 0xc1, 0xea, 0x97, 0xd4, 0x77, 0x4e, 0xaf, 0x5e, + 0x56, 0x7c, 0xbc, 0x9c, 0x7c, 0xb2, 0x9c, 0x0e, 0xac, 0x25, 0xca, 0x11, 0xd5, 0xf3, 0xad, 0x27, + 0x66, 0xbf, 0x62, 0xf2, 0x0f, 0xed, 0x90, 0xc9, 0xeb, 0x87, 0x8c, 0xe1, 0x01, 0xd9, 0xf1, 0x5c, + 0x97, 0x8e, 0xc2, 0x23, 0x4a, 0x7d, 0xd9, 0x98, 0x77, 0xb5, 0x7d, 0x56, 0x7b, 0xb8, 0x21, 0xc6, + 0x3c, 0x79, 0x72, 0x89, 0x0d, 0x48, 0xa0, 0x38, 0xa3, 0xfe, 0x14, 0x0b, 0xae, 0x98, 0xf8, 0x9b, + 0x0d, 0x6e, 0xe8, 0x4c, 0xa9, 0x37, 0x0f, 0x05, 0xc5, 0x95, 0x9f, 0xc6, 0x1a, 0xac, 0xc4, 0x2a, + 0xe4, 0xad, 0x36, 0x1e, 0xc0, 0xda, 0xae, 0x13, 0x8c, 0xd2, 0x4d, 0xd9, 0x80, 0xf2, 0x6c, 0x7e, + 0x62, 0xc5, 0x8f, 0xc7, 0x27, 0xf4, 0xca, 0x68, 0xc1, 0x7a, 0x32, 0x87, 0x28, 0xeb, 0xd7, 0xf2, + 0x50, 0xdc, 0x1f, 0x1e, 0xec, 0x90, 0x4d, 0xa8, 0x38, 0xee, 0xc8, 0x9b, 0x32, 0xe1, 0x80, 0x8f, + 0x86, 0xfa, 0xbe, 0x96, 0x6c, 0xdc, 0x82, 0x2a, 0xca, 0x14, 0x13, 0x6f, 0xf4, 0x4c, 0xb0, 0xe7, + 0x15, 0x06, 0x38, 0xf0, 0x46, 0xcf, 0xd8, 0xd6, 0xa4, 0x97, 0x33, 0xc7, 0x47, 0x75, 0x93, 0x54, + 0xa7, 0x14, 0x39, 0x3f, 0x1a, 0x25, 0x44, 0x4a, 0x17, 0xc1, 0x3a, 0x31, 0x66, 0x80, 0xf3, 0xe9, + 0xd5, 0x73, 0x64, 0x9d, 0xc6, 0xf4, 0x92, 0xbc, 0x0f, 0xe4, 0xd4, 0xf3, 0x9f, 0xdb, 0xbe, 0x62, + 0x2d, 0x5d, 0x41, 0xb6, 0x8b, 0xe6, 0x72, 0x94, 0x22, 0xd8, 0x26, 0xf2, 0x10, 0xd6, 0x34, 0x74, + 0xad, 0x60, 0xce, 0xe2, 0xad, 0x44, 0x89, 0xfb, 0xb2, 0x0a, 0xe3, 0x57, 0xf3, 0x40, 0x44, 0xfe, + 0x1d, 0xcf, 0x0d, 0x42, 0xdf, 0x76, 0xdc, 0x30, 0x88, 0x33, 0x9a, 0xb9, 0x04, 0xa3, 0x79, 0x0f, + 0x9a, 0xc8, 0xe6, 0xea, 0xdc, 0x66, 0x3e, 0xe2, 0xf9, 0xcd, 0x88, 0xe3, 0x7c, 0x0b, 0x16, 0x23, + 0x51, 0x43, 0x69, 0x1b, 0x8b, 0x66, 0x5d, 0x89, 0x1b, 0x0c, 0xeb, 0x03, 0x58, 0x65, 0x44, 0x44, + 0xb2, 0xd0, 0x4a, 0x75, 0xc2, 0x89, 0xed, 0xf2, 0xd4, 0xbe, 0x3c, 0xa2, 0x52, 0xb0, 0x41, 0xde, + 0xd4, 0x80, 0x86, 0xe2, 0x3a, 0x11, 0x93, 0x8f, 0x5c, 0x4d, 0xf0, 0x9d, 0x88, 0x93, 0x2d, 0x18, + 0x2c, 0x64, 0x0b, 0x06, 0xc6, 0xbf, 0xab, 0x42, 0x59, 0x0e, 0x23, 0x72, 0xf9, 0xa1, 0x73, 0x41, + 0x23, 0x2e, 0x9f, 0x7d, 0x31, 0xe1, 0xc1, 0xa7, 0x53, 0x2f, 0x54, 0xd2, 0x1d, 0xdf, 0x26, 0x75, + 0x0e, 0x14, 0xf2, 0x9d, 0x26, 0x61, 0x70, 0x25, 0x29, 0xa7, 0x7c, 0x52, 0xc2, 0xe0, 0xfc, 0xe3, + 0x2d, 0x28, 0x4b, 0x39, 0xa1, 0xa8, 0x74, 0x24, 0x0b, 0x23, 0x2e, 0x24, 0x6c, 0x42, 0x65, 0x64, + 0xcf, 0xec, 0x91, 0x13, 0x72, 0x16, 0xbf, 0x60, 0xaa, 0x6f, 0x56, 0xfa, 0xc4, 0x1b, 0xd9, 0x13, + 0xeb, 0xc4, 0x9e, 0xd8, 0xee, 0x88, 0x0a, 0xed, 0x63, 0x1d, 0x81, 0xdb, 0x1c, 0x46, 0xbe, 0x05, + 0x8b, 0xa2, 0x9d, 0x12, 0x8b, 0x2b, 0x21, 0x45, 0xeb, 0x25, 0x1a, 0x93, 0x44, 0xbd, 0x29, 0x9b, + 0x97, 0x53, 0xca, 0x65, 0xb6, 0x82, 0x59, 0xe5, 0x90, 0x3d, 0x8a, 0xbd, 0x15, 0xc9, 0xcf, 0xf9, + 0x1a, 0xae, 0xf2, 0xaa, 0x38, 0xf0, 0x2b, 0xbe, 0x7e, 0xd3, 0x82, 0x5b, 0x41, 0x13, 0xdc, 0xde, + 0x85, 0xe5, 0xb9, 0x1b, 0xd0, 0x30, 0x9c, 0xd0, 0xb1, 0x6a, 0x4b, 0x0d, 0x91, 0x9a, 0x2a, 0x41, + 0x36, 0x67, 0x0b, 0x56, 0xb8, 0xda, 0x34, 0xb0, 0x43, 0x2f, 0x38, 0x77, 0x02, 0x2b, 0xa0, 0xae, + 0x54, 0x9f, 0x2d, 0x63, 0xd2, 0x40, 0xa4, 0x0c, 0xb8, 0xca, 0x65, 0x23, 0x81, 0xef, 0xd3, 0x11, + 0x75, 0x2e, 0xe8, 0x18, 0x85, 0xba, 0x82, 0xb9, 0x16, 0xcb, 0x63, 0x8a, 0x44, 0x94, 0xd0, 0xe7, + 0x53, 0x6b, 0x3e, 0x1b, 0xdb, 0x8c, 0x79, 0x5f, 0xe4, 0x52, 0x92, 0x3b, 0x9f, 0x1e, 0x73, 0x08, + 0x79, 0x00, 0x52, 0x6a, 0x13, 0x6b, 0x66, 0x29, 0x76, 0x18, 0x31, 0xaa, 0x61, 0xd6, 0x05, 0x06, + 0x97, 0x2a, 0xef, 0xe8, 0x9b, 0xa5, 0xc9, 0x56, 0x18, 0x1e, 0xff, 0xd1, 0x86, 0x69, 0x41, 0x79, + 0xe6, 0x3b, 0x17, 0x76, 0x48, 0x5b, 0xcb, 0xfc, 0xec, 0x17, 0x9f, 0x8c, 0x80, 0x3b, 0xae, 0x13, + 0x3a, 0x76, 0xe8, 0xf9, 0x2d, 0x82, 0x69, 0x11, 0x80, 0xdc, 0x87, 0x65, 0x5c, 0x27, 0x41, 0x68, + 0x87, 0xf3, 0x40, 0x88, 0xac, 0x2b, 0x5c, 0x34, 0x64, 0x09, 0x03, 0x84, 0xa3, 0xd4, 0x4a, 0x3e, + 0x85, 0x75, 0xbe, 0x34, 0x52, 0x5b, 0x73, 0x55, 0x31, 0x24, 0x2b, 0x88, 0xb1, 0x13, 0xdf, 0xa3, + 0x9f, 0xc3, 0x86, 0x58, 0x2e, 0xa9, 0x9c, 0x6b, 0x2a, 0xe7, 0x2a, 0x47, 0x49, 0x64, 0xdd, 0x82, + 0x65, 0xd6, 0x34, 0x67, 0x64, 0x89, 0x12, 0xd8, 0xae, 0x58, 0x67, 0xbd, 0xc0, 0x4c, 0x4b, 0x3c, + 0xd1, 0xc4, 0xb4, 0x27, 0xf4, 0x8a, 0x7c, 0x17, 0x96, 0xf8, 0xf2, 0x41, 0xbd, 0x0c, 0x1e, 0xd9, + 0x9b, 0x78, 0x64, 0xaf, 0x89, 0xc1, 0xdd, 0x51, 0xa9, 0x78, 0x6a, 0x2f, 0x8e, 0x62, 0xdf, 0x6c, + 0x6b, 0x4c, 0x9c, 0x53, 0xca, 0xce, 0x89, 0xd6, 0x06, 0x5f, 0x6c, 0xf2, 0x9b, 0xed, 0xda, 0xf9, + 0x0c, 0x53, 0x5a, 0x9c, 0x58, 0xf3, 0x2f, 0x5c, 0xc7, 0x13, 0x2f, 0xa0, 0x52, 0xe1, 0xde, 0xba, + 0x29, 0x36, 0x24, 0x03, 0x4a, 0xf9, 0x8a, 0x09, 0xf0, 0x5c, 0x5b, 0xa2, 0xcc, 0x22, 0xb7, 0x70, + 0x61, 0x34, 0xb8, 0xd2, 0x44, 0x9a, 0x46, 0x18, 0xc3, 0x78, 0x6e, 0x3f, 0x97, 0x64, 0xfd, 0x35, + 0xa4, 0x26, 0xc0, 0x40, 0x82, 0xa0, 0xef, 0xc1, 0xb2, 0x98, 0x85, 0x88, 0x98, 0xb6, 0x6e, 0xe3, + 0x11, 0x79, 0x53, 0xf6, 0x31, 0x45, 0x6d, 0xcd, 0x26, 0x9f, 0x17, 0x8d, 0xfe, 0xee, 0x03, 0x91, + 0x93, 0xa2, 0x15, 0xf4, 0xfa, 0xcb, 0x0a, 0x5a, 0x16, 0xd3, 0x14, 0x81, 0x8c, 0xdf, 0xcb, 0x71, + 0x5e, 0x4b, 0x60, 0x07, 0x9a, 0xa6, 0x8a, 0xd3, 0x35, 0xcb, 0x73, 0x27, 0x57, 0x82, 0xd4, 0x01, + 0x07, 0xf5, 0xdd, 0x09, 0xd2, 0x1a, 0xc7, 0xd5, 0x51, 0xf8, 0xe1, 0x5d, 0x97, 0x40, 0x44, 0xba, + 0x03, 0xb5, 0xd9, 0xfc, 0x64, 0xe2, 0x8c, 0x38, 0x4a, 0x81, 0x97, 0xc2, 0x41, 0x88, 0xf0, 0x06, + 0xd4, 0xc5, 0x5a, 0xe7, 0x18, 0x45, 0xc4, 0xa8, 0x09, 0x18, 0xa2, 0x20, 0x73, 0x40, 0x7d, 0x24, + 0x76, 0x75, 0x13, 0x7f, 0x1b, 0xdb, 0xb0, 0x1a, 0x6f, 0xb4, 0xe0, 0x5c, 0xee, 0x43, 0x45, 0x50, + 0x52, 0xa9, 0xe6, 0x5d, 0x8c, 0x8f, 0x86, 0xa9, 0xd2, 0x8d, 0x7f, 0x5f, 0x82, 0x15, 0x39, 0x46, + 0x6c, 0xb2, 0x07, 0xf3, 0xe9, 0xd4, 0xf6, 0x33, 0x48, 0x74, 0xee, 0xc5, 0x24, 0x3a, 0x9f, 0x22, + 0xd1, 0x71, 0x25, 0x1e, 0xa7, 0xf0, 0x71, 0x25, 0x1e, 0x5b, 0x5d, 0x5c, 0x75, 0xa0, 0xdb, 0x99, + 0x1a, 0x02, 0x3c, 0xe4, 0xf6, 0xac, 0xd4, 0x81, 0x52, 0xca, 0x38, 0x50, 0xf4, 0xe3, 0x60, 0x21, + 0x71, 0x1c, 0xbc, 0x01, 0x7c, 0x19, 0xcb, 0xf5, 0x58, 0xe6, 0xda, 0x04, 0x84, 0x89, 0x05, 0xf9, + 0x0e, 0x2c, 0x25, 0x29, 0x30, 0x27, 0xf5, 0x8b, 0x19, 0xf4, 0xd7, 0x99, 0x52, 0x64, 0x6a, 0x34, + 0xe4, 0xaa, 0xa0, 0xbf, 0xce, 0x94, 0x1e, 0x60, 0x8a, 0xc4, 0xef, 0x00, 0xf0, 0xba, 0x71, 0x1b, + 0x03, 0x6e, 0xe3, 0xb7, 0x13, 0x2b, 0x53, 0x1b, 0xf5, 0x2d, 0xf6, 0x31, 0xf7, 0x29, 0xee, 0xeb, + 0x2a, 0xe6, 0xc4, 0x2d, 0xfd, 0x29, 0x2c, 0x7a, 0x33, 0xea, 0x5a, 0x11, 0x15, 0xac, 0x61, 0x51, + 0x4d, 0x51, 0x54, 0x57, 0xc2, 0xcd, 0x06, 0xc3, 0x53, 0x9f, 0xe4, 0x73, 0x3e, 0xc8, 0x54, 0xcb, + 0x59, 0xbf, 0x26, 0xe7, 0x22, 0x22, 0x46, 0x59, 0x3f, 0x42, 0x45, 0x99, 0x37, 0x99, 0x73, 0xd3, + 0x54, 0x03, 0xd7, 0x91, 0xd4, 0xd5, 0x9b, 0x2a, 0xc5, 0xd4, 0xb1, 0x8c, 0xdf, 0xc8, 0x41, 0x4d, + 0xeb, 0x03, 0x59, 0x83, 0xe5, 0x9d, 0x7e, 0xff, 0xa8, 0x63, 0xb6, 0x87, 0xdd, 0x2f, 0x3b, 0xd6, + 0xce, 0x41, 0x7f, 0xd0, 0x69, 0xde, 0x60, 0xe0, 0x83, 0xfe, 0x4e, 0xfb, 0xc0, 0xda, 0xeb, 0x9b, + 0x3b, 0x12, 0x9c, 0x23, 0xeb, 0x40, 0xcc, 0xce, 0x61, 0x7f, 0xd8, 0x89, 0xc1, 0xf3, 0xa4, 0x09, + 0xf5, 0x6d, 0xb3, 0xd3, 0xde, 0xd9, 0x17, 0x90, 0x02, 0x59, 0x85, 0xe6, 0xde, 0x71, 0x6f, 0xb7, + 0xdb, 0x7b, 0x6c, 0xed, 0xb4, 0x7b, 0x3b, 0x9d, 0x83, 0xce, 0x6e, 0xb3, 0x48, 0x1a, 0x50, 0x6d, + 0x6f, 0xb7, 0x7b, 0xbb, 0xfd, 0x5e, 0x67, 0xb7, 0x59, 0x32, 0xfe, 0x38, 0x07, 0x10, 0x35, 0x94, + 0xd1, 0xd5, 0xa8, 0xa9, 0xba, 0x91, 0x78, 0x2d, 0xd5, 0x29, 0x4e, 0x57, 0xfd, 0xd8, 0x37, 0x79, + 0x08, 0x65, 0x6f, 0x1e, 0x8e, 0xbc, 0x29, 0x17, 0x22, 0x16, 0x1f, 0xb6, 0x52, 0xf9, 0xfa, 0x3c, + 0xdd, 0x94, 0x88, 0x31, 0x43, 0x70, 0xe1, 0x65, 0x86, 0xe0, 0xb8, 0xc5, 0x99, 0xf3, 0x75, 0x9a, + 0xc5, 0xf9, 0x36, 0x40, 0xf0, 0x9c, 0xd2, 0x19, 0x6a, 0xda, 0xc4, 0x2e, 0xa8, 0x22, 0x64, 0xc8, + 0xe4, 0xd2, 0xff, 0x94, 0x83, 0x35, 0x5c, 0x4b, 0xe3, 0x24, 0x11, 0xbb, 0x0b, 0xb5, 0x91, 0xe7, + 0xcd, 0x28, 0x63, 0xaa, 0x15, 0xbf, 0xa6, 0x83, 0x18, 0x81, 0xe2, 0x04, 0xf9, 0xd4, 0xf3, 0x47, + 0x54, 0xd0, 0x30, 0x40, 0xd0, 0x1e, 0x83, 0xb0, 0x3d, 0x24, 0x36, 0x21, 0xc7, 0xe0, 0x24, 0xac, + 0xc6, 0x61, 0x1c, 0x65, 0x1d, 0x16, 0x4e, 0x7c, 0x6a, 0x8f, 0xce, 0x05, 0xf5, 0x12, 0x5f, 0xe4, + 0xdb, 0x91, 0xc6, 0x71, 0xc4, 0xf6, 0xc4, 0x84, 0xf2, 0xc6, 0x57, 0xcc, 0x25, 0x01, 0xdf, 0x11, + 0x60, 0x76, 0xce, 0xdb, 0x27, 0xb6, 0x3b, 0xf6, 0x5c, 0x3a, 0x16, 0xf2, 0x7f, 0x04, 0x30, 0x8e, + 0x60, 0x3d, 0xd9, 0x3f, 0x41, 0xef, 0x3e, 0xd1, 0xe8, 0x1d, 0x17, 0x8a, 0x37, 0xaf, 0xdf, 0x63, + 0x1a, 0xed, 0xfb, 0xcf, 0x45, 0x28, 0x32, 0x81, 0xe7, 0x5a, 0xd9, 0x48, 0x97, 0x6d, 0x0b, 0x29, + 0xf7, 0x00, 0x54, 0x6c, 0x72, 0x06, 0x4c, 0x4c, 0x16, 0x42, 0x90, 0xf1, 0x52, 0xc9, 0x3e, 0x1d, + 0x5d, 0x48, 0x99, 0x05, 0x21, 0x26, 0x1d, 0x5d, 0xa0, 0xa2, 0xc3, 0x0e, 0x79, 0x5e, 0x4e, 0xaf, + 0xca, 0x81, 0x1d, 0x62, 0x4e, 0x91, 0x84, 0xf9, 0xca, 0x2a, 0x09, 0x73, 0xb5, 0xa0, 0xec, 0xb8, + 0x27, 0xde, 0xdc, 0x95, 0x6a, 0x25, 0xf9, 0x89, 0xde, 0x08, 0x48, 0x49, 0xd9, 0xd1, 0xce, 0xa9, + 0x51, 0x85, 0x01, 0x86, 0xec, 0x70, 0xff, 0x10, 0xaa, 0xc1, 0x95, 0x3b, 0xd2, 0x69, 0xd0, 0xaa, + 0x18, 0x1f, 0xd6, 0xfb, 0xad, 0xc1, 0x95, 0x3b, 0xc2, 0x15, 0x5f, 0x09, 0xc4, 0x2f, 0xf2, 0x08, + 0x2a, 0xca, 0x4a, 0xc7, 0x4f, 0x90, 0x9b, 0x7a, 0x0e, 0x69, 0x9a, 0xe3, 0x3a, 0x3a, 0x85, 0x4a, + 0x3e, 0x80, 0x05, 0xd4, 0xd6, 0x07, 0xad, 0x3a, 0x66, 0x92, 0x02, 0x2f, 0x6b, 0x06, 0x3a, 0x02, + 0xd0, 0x31, 0xda, 0xcc, 0x4c, 0x81, 0xc6, 0x86, 0xe9, 0x74, 0x62, 0xcf, 0x84, 0xee, 0xbc, 0xc1, + 0xed, 0xe9, 0x0c, 0xc2, 0x15, 0xe7, 0x77, 0xa1, 0x8e, 0x16, 0x50, 0xc4, 0x71, 0x39, 0x1f, 0x5a, + 0x30, 0x81, 0xc1, 0xf6, 0x26, 0xf6, 0xac, 0x17, 0x6c, 0x3e, 0x81, 0x46, 0xac, 0x31, 0xba, 0x0a, + 0xad, 0xc1, 0x55, 0x68, 0x6f, 0xe9, 0x2a, 0xb4, 0xe8, 0x28, 0x14, 0xd9, 0x74, 0x95, 0xda, 0x11, + 0x54, 0xe4, 0x58, 0x30, 0x9a, 0x73, 0xdc, 0x7b, 0xd2, 0xeb, 0x7f, 0xd5, 0xb3, 0x06, 0x4f, 0x7b, + 0x3b, 0xcd, 0x1b, 0x64, 0x09, 0x6a, 0xed, 0x1d, 0x24, 0x63, 0x08, 0xc8, 0x31, 0x94, 0xa3, 0xf6, + 0x60, 0xa0, 0x20, 0x79, 0x86, 0x72, 0xd4, 0xed, 0xf5, 0x3a, 0xbb, 0x1c, 0x50, 0x30, 0xf6, 0xa0, + 0x99, 0xec, 0x3b, 0x5b, 0xe5, 0xa1, 0x84, 0x09, 0xbb, 0x64, 0x04, 0x88, 0xac, 0x1f, 0x79, 0xcd, + 0xfa, 0x61, 0x3c, 0x82, 0x26, 0x3b, 0xe9, 0xd9, 0xe0, 0xeb, 0xee, 0x0a, 0x13, 0xc6, 0x8b, 0xeb, + 0xb6, 0xc9, 0x8a, 0x59, 0xe3, 0x30, 0xac, 0xca, 0xf8, 0x04, 0x96, 0xb5, 0x6c, 0x91, 0xfe, 0x88, + 0x71, 0x0f, 0x49, 0xfd, 0x11, 0x4a, 0xfe, 0x3c, 0xc5, 0xd8, 0x80, 0x35, 0xf6, 0xd9, 0xb9, 0xa0, + 0x6e, 0x38, 0x98, 0x9f, 0x70, 0x2f, 0x17, 0xc7, 0x73, 0x8d, 0x5f, 0xcd, 0x41, 0x55, 0xa5, 0x5c, + 0xbf, 0x6d, 0xb6, 0x84, 0xaa, 0x89, 0xd3, 0xc9, 0x4d, 0xad, 0x06, 0xcc, 0xb8, 0x85, 0x7f, 0x23, + 0x95, 0x93, 0xb1, 0x05, 0x55, 0x05, 0xc2, 0x41, 0xec, 0x74, 0x4c, 0xab, 0xdf, 0x3b, 0xe8, 0xf6, + 0xd8, 0x69, 0xc1, 0xc6, 0x19, 0x01, 0x7b, 0x7b, 0x08, 0xc9, 0x19, 0x4d, 0x58, 0x7c, 0x4c, 0xc3, + 0xae, 0x7b, 0xea, 0x89, 0xc1, 0x30, 0x7e, 0x7d, 0x01, 0x96, 0x14, 0x28, 0x52, 0x4c, 0x5d, 0x50, + 0x3f, 0x70, 0x3c, 0x17, 0x17, 0x4e, 0xd5, 0x94, 0x9f, 0x8c, 0xde, 0x09, 0xb1, 0x0d, 0xf9, 0x8e, + 0x55, 0x4c, 0x15, 0x82, 0x1e, 0x32, 0x1d, 0xef, 0xc0, 0x92, 0x33, 0xa6, 0x6e, 0xe8, 0x84, 0x57, + 0x56, 0xcc, 0xa6, 0xb0, 0x28, 0xc1, 0x82, 0xf1, 0x58, 0x85, 0x92, 0x3d, 0x71, 0x6c, 0xe9, 0x3d, + 0xc4, 0x3f, 0x18, 0x74, 0xe4, 0x4d, 0x3c, 0x1f, 0x05, 0x99, 0xaa, 0xc9, 0x3f, 0xc8, 0x03, 0x58, + 0x65, 0x42, 0x95, 0x6e, 0x04, 0x43, 0x92, 0xc5, 0xcd, 0x1b, 0xc4, 0x9d, 0x4f, 0x8f, 0x22, 0x43, + 0x18, 0x4b, 0x61, 0xec, 0x06, 0xcb, 0x21, 0xf8, 0x4b, 0x95, 0x81, 0x2b, 0x4a, 0x96, 0xdd, 0xf9, + 0xb4, 0x8d, 0x29, 0x0a, 0xff, 0x21, 0xac, 0x31, 0x7c, 0xc5, 0x91, 0xaa, 0x1c, 0x4b, 0x98, 0x83, + 0x15, 0xd6, 0x15, 0x69, 0x2a, 0xcf, 0x2d, 0xa8, 0xf2, 0x56, 0xb1, 0x25, 0x21, 0xac, 0x65, 0xd8, + 0x14, 0xea, 0x07, 0x29, 0x47, 0x1f, 0xae, 0x19, 0x48, 0x3a, 0xfa, 0x68, 0xae, 0x42, 0x95, 0xa4, + 0xab, 0xd0, 0x43, 0x58, 0x3b, 0x61, 0x6b, 0xf4, 0x9c, 0xda, 0x63, 0xea, 0x5b, 0xd1, 0xca, 0xe7, + 0xf2, 0xe7, 0x0a, 0x4b, 0xdc, 0xc7, 0x34, 0xb5, 0x51, 0x18, 0x6b, 0xc8, 0x28, 0x11, 0x1d, 0x5b, + 0xa1, 0x67, 0x21, 0xc7, 0x28, 0xd4, 0xb6, 0x0d, 0x0e, 0x1e, 0x7a, 0x3b, 0x0c, 0x18, 0xc7, 0x3b, + 0xf3, 0xed, 0xd9, 0xb9, 0x90, 0x0e, 0x15, 0xde, 0x63, 0x06, 0x24, 0xaf, 0x41, 0x99, 0xed, 0x09, + 0x97, 0x72, 0xef, 0x08, 0x2e, 0x77, 0x49, 0x10, 0x79, 0x0b, 0x16, 0xb0, 0x8e, 0xa0, 0xd5, 0xc4, + 0x0d, 0x51, 0x8f, 0xce, 0x0e, 0xc7, 0x35, 0x45, 0x1a, 0xe3, 0xbf, 0xe7, 0xbe, 0xc3, 0x09, 0x5b, + 0xd5, 0xc4, 0xdf, 0xe4, 0x7b, 0x1a, 0x95, 0x5c, 0xc1, 0xbc, 0x6f, 0x89, 0xbc, 0x89, 0xa5, 0x78, + 0x1d, 0xc1, 0xfc, 0x46, 0xc9, 0xd7, 0xf7, 0x8b, 0x95, 0x5a, 0xb3, 0x6e, 0xb4, 0xd0, 0xbf, 0xc9, + 0xa4, 0x23, 0xef, 0x82, 0xfa, 0x57, 0xb1, 0x3d, 0x92, 0x83, 0x8d, 0x54, 0x52, 0xe4, 0xe9, 0xe0, + 0x0b, 0xb8, 0x35, 0xf5, 0xc6, 0x92, 0x4b, 0xa8, 0x4b, 0xe0, 0xa1, 0x37, 0x66, 0xdc, 0xcc, 0xb2, + 0x42, 0x3a, 0x75, 0x5c, 0x27, 0x38, 0xa7, 0x63, 0xc1, 0x2c, 0x34, 0x65, 0xc2, 0x9e, 0x80, 0x33, + 0x96, 0x7c, 0xe6, 0x7b, 0x67, 0xea, 0xec, 0xcc, 0x99, 0xea, 0xdb, 0xf8, 0x14, 0x4a, 0x7c, 0x06, + 0xd9, 0x46, 0xc1, 0xf9, 0xcd, 0x89, 0x8d, 0x82, 0xd0, 0x16, 0x94, 0x5d, 0x1a, 0x3e, 0xf7, 0xfc, + 0x67, 0x52, 0x03, 0x2d, 0x3e, 0x8d, 0x1f, 0xa1, 0x96, 0x55, 0x39, 0xaa, 0x71, 0x6d, 0x04, 0x5b, + 0xc2, 0x7c, 0x09, 0x06, 0xe7, 0xb6, 0x50, 0xfc, 0x56, 0x10, 0x30, 0x38, 0xb7, 0x53, 0x4b, 0x38, + 0x9f, 0xf6, 0x55, 0x7b, 0x0b, 0x16, 0xa5, 0x6b, 0x5c, 0x60, 0x4d, 0xe8, 0x69, 0x28, 0xb6, 0x64, + 0x5d, 0xf8, 0xc5, 0x05, 0x07, 0xf4, 0x34, 0x34, 0x0e, 0x61, 0x59, 0x6c, 0x9a, 0xfe, 0x8c, 0xca, + 0xaa, 0x3f, 0xcb, 0x12, 0x93, 0x6a, 0x0f, 0x57, 0xe2, 0xfc, 0x07, 0xe7, 0xf4, 0x62, 0xb2, 0x93, + 0xf1, 0x83, 0x48, 0xa5, 0xc8, 0xb8, 0x13, 0x51, 0x9e, 0x10, 0x56, 0xa4, 0x41, 0x55, 0x3a, 0x6d, + 0x28, 0x91, 0xc8, 0x19, 0xb3, 0xd1, 0x09, 0xe6, 0xa3, 0x91, 0x74, 0x59, 0xac, 0x98, 0xf2, 0xd3, + 0xf8, 0xdf, 0x39, 0x58, 0xc1, 0xc2, 0xa4, 0x98, 0x27, 0x4e, 0x8a, 0x1f, 0xbb, 0x91, 0x6c, 0x7e, + 0x74, 0x96, 0x90, 0x7f, 0xbc, 0xdc, 0x22, 0x94, 0xb4, 0xf6, 0x14, 0x33, 0xad, 0x3d, 0xdf, 0x86, + 0xe6, 0x98, 0x4e, 0x1c, 0x5c, 0x4e, 0x92, 0xcb, 0xe2, 0x6c, 0xed, 0x92, 0x84, 0x4b, 0xd5, 0x43, + 0xca, 0xc4, 0xb4, 0x90, 0x36, 0x3f, 0xfe, 0x8d, 0x1c, 0x2c, 0x73, 0x46, 0x0f, 0x15, 0x3e, 0x62, + 0x40, 0xbf, 0x90, 0x9a, 0x0d, 0x41, 0x76, 0x45, 0xdf, 0x23, 0x06, 0x08, 0xa1, 0x1c, 0x79, 0xff, + 0x86, 0xd0, 0x78, 0x08, 0x28, 0xf9, 0x0e, 0x8a, 0xb0, 0xae, 0x85, 0x40, 0xc1, 0xc0, 0xdf, 0xcc, + 0x60, 0x2d, 0x55, 0x76, 0x26, 0xdf, 0xba, 0x08, 0xda, 0xae, 0xc0, 0x02, 0x57, 0x9f, 0x19, 0x7b, + 0xd0, 0x88, 0x55, 0x13, 0x33, 0x2b, 0xd5, 0xb9, 0x59, 0x29, 0x65, 0xf3, 0xce, 0xa7, 0x6d, 0xde, + 0x57, 0xb0, 0x62, 0x52, 0x7b, 0x7c, 0xb5, 0xe7, 0xf9, 0x47, 0xc1, 0x49, 0xb8, 0xc7, 0xb9, 0x67, + 0x76, 0x56, 0x29, 0x2f, 0x97, 0x98, 0x1d, 0x46, 0xda, 0xf3, 0xe5, 0x20, 0x7e, 0x0b, 0x16, 0x23, + 0x77, 0x18, 0x4d, 0x63, 0xdf, 0x50, 0x1e, 0x31, 0xc8, 0x74, 0x11, 0x28, 0xce, 0x82, 0x93, 0x50, + 0xe8, 0xec, 0xf1, 0xb7, 0xf1, 0x4f, 0x4b, 0x40, 0xd8, 0xaa, 0x4f, 0x2c, 0xac, 0xd4, 0xb4, 0xe4, + 0xd2, 0x96, 0xbf, 0x84, 0xb3, 0x4f, 0x3e, 0xe5, 0xec, 0xf3, 0x00, 0x88, 0x86, 0x20, 0x7d, 0x90, + 0x0a, 0xca, 0x07, 0xa9, 0x19, 0xe1, 0x0a, 0x17, 0xa4, 0x07, 0xb0, 0x2a, 0xc4, 0x95, 0x78, 0x77, + 0x70, 0x99, 0x99, 0x84, 0xcb, 0x2d, 0xb1, 0x3e, 0x49, 0x47, 0x1f, 0xa9, 0x06, 0x2f, 0x70, 0x47, + 0x1f, 0xa9, 0xad, 0xd2, 0x16, 0xf3, 0xc2, 0x4b, 0x17, 0x73, 0x39, 0x73, 0x31, 0x6b, 0xda, 0xcb, + 0x4a, 0x5c, 0x7b, 0x99, 0xd2, 0xc3, 0x73, 0xfe, 0x3c, 0xa6, 0x87, 0xbf, 0x07, 0x4d, 0xa9, 0xc9, + 0x52, 0x3a, 0x52, 0xe1, 0x01, 0x22, 0x94, 0x55, 0x52, 0x4b, 0x1a, 0x33, 0x34, 0xd6, 0x5e, 0xc5, + 0xe2, 0x59, 0xcf, 0xb6, 0x78, 0xa6, 0x75, 0x7e, 0x8d, 0x0c, 0x9d, 0xdf, 0xa3, 0xc8, 0xc1, 0x23, + 0x38, 0x77, 0xa6, 0xc8, 0x48, 0x45, 0x1e, 0xaa, 0x62, 0x90, 0x07, 0xe7, 0xce, 0xd4, 0x94, 0xae, + 0x56, 0xec, 0x83, 0xec, 0xc0, 0x1d, 0xd1, 0x9f, 0x0c, 0x2f, 0x29, 0x3e, 0x0a, 0x4b, 0xb8, 0x54, + 0x36, 0x39, 0xda, 0x61, 0xc2, 0x61, 0x2a, 0x31, 0x28, 0xd2, 0xc7, 0x26, 0xe0, 0x8a, 0x63, 0x39, + 0x28, 0x87, 0xdc, 0xc9, 0x06, 0xc9, 0x03, 0x43, 0x11, 0x4a, 0xc5, 0xe0, 0x02, 0xf9, 0xae, 0x86, + 0x59, 0x9b, 0xda, 0x97, 0x07, 0xa8, 0x34, 0x0c, 0x2e, 0x8c, 0x3f, 0xcd, 0x41, 0x93, 0x2d, 0xe1, + 0x18, 0x75, 0xf8, 0x1c, 0x90, 0xde, 0xbd, 0x22, 0x71, 0xa8, 0x31, 0x5c, 0x49, 0x1b, 0x3e, 0x05, + 0xdc, 0xec, 0x96, 0x37, 0xa3, 0xae, 0x20, 0x0d, 0xad, 0x38, 0x69, 0x88, 0x8e, 0x89, 0xfd, 0x1b, + 0x5c, 0xea, 0x64, 0x10, 0xf2, 0x39, 0x54, 0xd9, 0x9e, 0xc2, 0xc5, 0x2b, 0xbc, 0xc3, 0x37, 0x95, + 0x26, 0x21, 0xb5, 0xbd, 0x59, 0xd6, 0x99, 0xf8, 0xcc, 0x72, 0xa1, 0x2a, 0x66, 0xb8, 0x50, 0x69, + 0xb4, 0x67, 0x1f, 0xe0, 0x09, 0xbd, 0x62, 0x83, 0x10, 0x7a, 0x3e, 0xe3, 0xd5, 0xd8, 0x16, 0x3b, + 0xb5, 0xa7, 0x8e, 0xd0, 0x66, 0x96, 0xcc, 0xea, 0x33, 0x7a, 0xb5, 0x87, 0x00, 0xb6, 0xb6, 0x58, + 0x72, 0x44, 0x80, 0x4a, 0x66, 0xe5, 0x19, 0xbd, 0xe2, 0xd4, 0xc7, 0x82, 0xc6, 0x13, 0x7a, 0xb5, + 0x4b, 0xb9, 0x30, 0xe0, 0xf9, 0x6c, 0xd0, 0x7d, 0xfb, 0x39, 0xe3, 0xfe, 0x63, 0x2e, 0x3e, 0x35, + 0xdf, 0x7e, 0xfe, 0x84, 0x5e, 0x49, 0x77, 0xa3, 0x32, 0x4b, 0x9f, 0x78, 0x23, 0xc1, 0xbe, 0x48, + 0x05, 0x52, 0xd4, 0x28, 0x73, 0xe1, 0x19, 0xfe, 0x36, 0xfe, 0x24, 0x07, 0x0d, 0xd6, 0x7e, 0x3c, + 0x79, 0x70, 0x15, 0x09, 0x9f, 0xe1, 0x5c, 0xe4, 0x33, 0xfc, 0x50, 0x10, 0x64, 0x7e, 0x8c, 0xe5, + 0xaf, 0x3f, 0xc6, 0x70, 0x6e, 0xf8, 0x19, 0xf6, 0x21, 0x54, 0xf9, 0xc2, 0x60, 0xe4, 0xa7, 0x10, + 0x9b, 0xe0, 0x58, 0x87, 0xcc, 0x0a, 0xa2, 0x3d, 0xe1, 0xfe, 0x87, 0x9a, 0xae, 0x9e, 0x0f, 0x71, + 0xd5, 0x57, 0x1a, 0xfa, 0x8c, 0x69, 0x28, 0x5d, 0xe3, 0x7f, 0xa8, 0x2b, 0xc2, 0x17, 0x92, 0x8a, + 0x70, 0xc3, 0x85, 0x0a, 0x9b, 0x6a, 0xec, 0x6c, 0x46, 0xa1, 0xb9, 0xac, 0x42, 0x19, 0xb3, 0x63, + 0xb3, 0xf3, 0x8c, 0xd1, 0xe8, 0xbc, 0x60, 0x76, 0xec, 0x80, 0xb2, 0x82, 0x58, 0xc3, 0x5d, 0xcf, + 0x42, 0xcd, 0xb2, 0xd0, 0xb9, 0x56, 0xcc, 0xaa, 0xeb, 0x1d, 0x71, 0x80, 0xf1, 0x97, 0x72, 0x50, + 0xd3, 0xf6, 0x2c, 0x9a, 0x1a, 0xd4, 0x70, 0xf2, 0x0d, 0x1e, 0xdf, 0x01, 0xb1, 0xf9, 0xd8, 0xbf, + 0x61, 0x36, 0x46, 0xb1, 0x09, 0xda, 0x12, 0x4b, 0x19, 0x73, 0xe6, 0x63, 0xfa, 0x2d, 0xd9, 0x2f, + 0xb9, 0x7e, 0xd9, 0xef, 0xed, 0x05, 0x28, 0x32, 0x54, 0xe3, 0x0b, 0x58, 0xd6, 0x9a, 0xc1, 0xf5, + 0x3f, 0xaf, 0x3a, 0x00, 0xc6, 0x2f, 0xa8, 0xcc, 0xac, 0x0e, 0x6e, 0xbb, 0x97, 0xae, 0x9e, 0x74, + 0xcc, 0xc7, 0x45, 0xb8, 0x94, 0x72, 0x10, 0x8e, 0xcc, 0x2b, 0x7a, 0x1f, 0x1a, 0xbf, 0x92, 0x83, + 0x15, 0xad, 0xf8, 0x3d, 0xc7, 0xb5, 0x27, 0xce, 0x8f, 0xf0, 0x18, 0x0b, 0x9c, 0x33, 0x37, 0x51, + 0x01, 0x07, 0x7d, 0x9d, 0x0a, 0xc8, 0x5d, 0xa8, 0x73, 0xdf, 0x72, 0x7e, 0x73, 0x41, 0x1c, 0xb3, + 0x80, 0x30, 0xd3, 0x7e, 0x3e, 0xbc, 0x34, 0xfe, 0x66, 0x1e, 0x56, 0x45, 0x13, 0xf0, 0x0a, 0x80, + 0xc3, 0x58, 0xdd, 0xc3, 0xe0, 0x8c, 0x7c, 0x0e, 0x0d, 0x36, 0x7c, 0x96, 0x4f, 0xcf, 0x9c, 0x20, + 0xa4, 0xd2, 0xad, 0x20, 0x83, 0x1a, 0x33, 0x4e, 0x86, 0xa1, 0x9a, 0x02, 0x93, 0x7c, 0x01, 0x35, + 0xcc, 0xca, 0x55, 0x70, 0x62, 0xae, 0x5a, 0xe9, 0x8c, 0x7c, 0x2e, 0xf6, 0x6f, 0x98, 0x10, 0x44, + 0x33, 0xf3, 0x05, 0xd4, 0x70, 0x9a, 0x2f, 0x70, 0xac, 0x13, 0xc4, 0x2e, 0x35, 0x17, 0x2c, 0xf3, + 0x2c, 0x9a, 0x99, 0x36, 0x34, 0x38, 0xb9, 0x13, 0x23, 0x29, 0xfc, 0x86, 0x37, 0xd3, 0xd9, 0xe5, + 0x58, 0xb3, 0xc6, 0xcf, 0xb4, 0xef, 0xed, 0x2a, 0x94, 0x43, 0xdf, 0x39, 0x3b, 0xa3, 0xbe, 0xb1, + 0xae, 0x86, 0x86, 0xd1, 0x71, 0x3a, 0x08, 0xe9, 0x8c, 0xc9, 0x30, 0xc6, 0xbf, 0xcc, 0x41, 0x4d, + 0x50, 0xe6, 0x1f, 0xdb, 0x63, 0x61, 0x33, 0xa1, 0xac, 0xad, 0x6a, 0xba, 0xd9, 0x77, 0x60, 0x69, + 0xca, 0x04, 0x2e, 0x27, 0xbc, 0x8a, 0xbb, 0x2b, 0x2c, 0x4a, 0xb0, 0x90, 0x25, 0xb6, 0x60, 0x05, + 0x45, 0x8b, 0xc0, 0x0a, 0x9d, 0x89, 0x25, 0x13, 0xc5, 0x0d, 0x99, 0x65, 0x9e, 0x34, 0x74, 0x26, + 0x87, 0x22, 0x81, 0x71, 0xd8, 0x41, 0x68, 0x9f, 0x51, 0x41, 0x1d, 0xf8, 0x07, 0x13, 0xe2, 0x12, + 0xba, 0x00, 0x29, 0xc4, 0xfd, 0xdf, 0x65, 0xd8, 0x48, 0x25, 0x09, 0x21, 0x4e, 0x59, 0x87, 0x27, + 0xce, 0xf4, 0xc4, 0x53, 0xd6, 0x89, 0x9c, 0x66, 0x1d, 0x3e, 0x60, 0x29, 0xd2, 0x3a, 0x41, 0x61, + 0x4d, 0x2e, 0x59, 0x34, 0x2f, 0x28, 0x75, 0x41, 0x1e, 0x85, 0xd9, 0x0f, 0xe3, 0xc7, 0x60, 0xb2, + 0x3a, 0x09, 0xd7, 0xf9, 0xc2, 0x95, 0x59, 0x0a, 0x16, 0x90, 0x3f, 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, 0x15, 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, 0xc9, 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, 0xef, 0xf1, 0xe9, 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, 0x7f, 0x3f, 0x0f, 0x35, 0x2d, 0x91, 0x8d, 0x22, + 0x5f, 0xb2, 0x9a, 0x53, 0x28, 0xe7, 0x2d, 0x51, 0x31, 0x83, 0x57, 0x0b, 0x70, 0x71, 0x62, 0x3a, + 0xdf, 0x5c, 0x82, 0x91, 0x44, 0x84, 0x2d, 0x58, 0x91, 0xa6, 0x6c, 0x1a, 0x39, 0xcd, 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, 0x0b, 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, 0x7f, 0x66, 0xfc, 0x43, 0xa4, 0x93, 0xd5, 0xfc, 0x11, + 0xf8, 0xe6, 0x6c, 0xaa, 0x04, 0xd9, 0x8a, 0x4f, 0x93, 0x5e, 0x5b, 0x95, 0xd8, 0x85, 0x53, 0x8d, + 0x81, 0x4a, 0x38, 0x6f, 0x1d, 0xc3, 0x82, 0xed, 0x8e, 0xce, 0x3d, 0x5f, 0xd0, 0xc1, 0x9f, 0xf9, + 0xda, 0xc7, 0xe7, 0x56, 0x1b, 0xf3, 0x23, 0xd7, 0x66, 0x8a, 0xc2, 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, 0xa2, 0xc4, 0xb4, 0x75, 0xea, 0xb7, 0x8a, 0x4a, 0xa7, 0x8a, 0x89, 0x42, 0xc8, 0xff, + 0x08, 0xea, 0x3a, 0x7b, 0x23, 0x56, 0x44, 0xc2, 0x25, 0x86, 0x89, 0xf7, 0x9e, 0x46, 0xab, 0x77, + 0x80, 0x3b, 0x44, 0x8c, 0x55, 0xb6, 0x7c, 0x8c, 0x6f, 0xcd, 0xb0, 0x2c, 0xa3, 0x7c, 0x14, 0x5b, + 0x86, 0x7f, 0x0e, 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, 0x30, 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, 0x0b, 0x8c, 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, + 0x67, 0x01, 0xc8, 0x0f, 0xe6, 0xd4, 0xbf, 0xc2, 0x6b, 0xcd, 0xc1, 0xcb, 0xee, 0x50, 0x48, 0x4d, + 0x65, 0xfe, 0x95, 0xa2, 0x1b, 0x64, 0x45, 0x17, 0x28, 0xbe, 0x3c, 0xba, 0x40, 0xe9, 0x65, 0xd1, + 0x05, 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, 0xc6, + 0xde, 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, 0xf5, 0xa0, 0x96, 0x8c, 0x7a, 0xf0, 0xcb, 0xd9, 0x51, 0x0f, 0x1a, 0x31, + 0x62, 0x96, 0x9e, 0xe2, 0xaf, 0x15, 0xfc, 0x20, 0x1d, 0xcc, 0x61, 0xf1, 0xeb, 0x04, 0x73, 0x58, + 0xca, 0x0a, 0xe6, 0xf0, 0x21, 0xd4, 0xf0, 0x0e, 0xbd, 0x75, 0x8e, 0xce, 0xcc, 0xdc, 0x25, 0xa1, + 0xa9, 0x5f, 0xb2, 0xdf, 0x77, 0xdc, 0xd0, 0x04, 0x5f, 0xfe, 0x0c, 0xd2, 0x71, 0x15, 0x96, 0x5f, + 0x29, 0xae, 0xc2, 0x37, 0x13, 0x34, 0x41, 0xdc, 0xf5, 0xdf, 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, 0x02, 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, 0xe0, 0x05, 0x22, 0x0d, 0xe3, + 0xc0, 0x70, 0x8b, 0xba, 0x35, 0xf3, 0xbd, 0x13, 0xac, 0x24, 0x67, 0xd6, 0x04, 0xec, 0xc8, 0xf7, + 0x4e, 0x8c, 0xbf, 0x52, 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, + 0x4d, 0x77, 0xf1, 0x45, 0xde, 0x87, 0x95, 0x78, 0xb9, 0x9c, 0x14, 0x09, 0xc9, 0x40, 0x2f, 0x18, + 0x69, 0xd2, 0x4d, 0x60, 0x74, 0x24, 0xba, 0xeb, 0x5e, 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, 0x61, 0x4d, 0x6e, 0xcb, 0x7b, 0x28, 0xde, 0x6c, 0x2b, 0x63, 0x37, 0x37, 0x46, 0x3a, + 0x6c, 0xf3, 0x7b, 0x40, 0x7e, 0xc2, 0xc8, 0x21, 0x43, 0xa8, 0xaa, 0x0e, 0xa5, 0xe2, 0x95, 0xd4, + 0x52, 0xf1, 0x4a, 0x18, 0x21, 0xe5, 0x9c, 0x9e, 0x3a, 0x23, 0x40, 0x63, 0xf5, 0xc4, 0x0d, 0x2e, + 0xe3, 0x04, 0xaa, 0xaa, 0xd7, 0x68, 0x93, 0xf2, 0xbc, 0xd0, 0x0a, 0xce, 0x6d, 0x71, 0x1d, 0xb2, + 0x6e, 0x56, 0x19, 0x64, 0xc0, 0x00, 0x64, 0x0d, 0x16, 0x02, 0x1a, 0x46, 0x56, 0x87, 0x52, 0x40, + 0x43, 0x6e, 0x82, 0x1a, 0x9d, 0x3b, 0x93, 0x71, 0xec, 0x26, 0x3d, 0x20, 0x88, 0x9b, 0xf5, 0xfe, + 0x4b, 0x0e, 0x4a, 0x3c, 0xd2, 0xc8, 0xdb, 0xb0, 0xc4, 0xdb, 0xa4, 0x3c, 0xdc, 0x85, 0x1b, 0x12, + 0x67, 0x4a, 0x87, 0xc2, 0xb9, 0x9d, 0xed, 0x55, 0x2d, 0x74, 0x53, 0xc4, 0xdb, 0x68, 0xe1, 0x9b, + 0xee, 0x40, 0x55, 0x75, 0x4f, 0x5b, 0xcf, 0x15, 0xd9, 0x3b, 0xf2, 0x3a, 0x14, 0xcf, 0xbd, 0x99, + 0x54, 0xc6, 0x42, 0x34, 0x5b, 0x26, 0xc2, 0xa3, 0xb6, 0xb0, 0x3a, 0xa2, 0xdb, 0x6b, 0x05, 0xd1, + 0x16, 0x56, 0x89, 0x8c, 0xbf, 0x90, 0x18, 0xc7, 0x85, 0x8c, 0x71, 0x3c, 0x86, 0x25, 0x46, 0x9c, + 0x34, 0x5f, 0xa8, 0xeb, 0x4f, 0xf2, 0x6f, 0x33, 0xa1, 0x6b, 0x34, 0x99, 0x8f, 0xa9, 0xae, 0x0e, + 0x47, 0x77, 0x65, 0x01, 0x97, 0xc2, 0xae, 0xf1, 0x3b, 0x39, 0x4e, 0xf4, 0x58, 0xb9, 0xe4, 0x1e, + 0x14, 0x5d, 0xe9, 0x37, 0x15, 0x89, 0x56, 0xea, 0xa6, 0x27, 0xc3, 0x33, 0x11, 0x83, 0x2d, 0x0f, + 0xf4, 0x36, 0xd2, 0x4b, 0x6f, 0x98, 0x35, 0x77, 0x3e, 0x55, 0xda, 0xe4, 0x6f, 0xc9, 0x6e, 0x25, + 0x34, 0xb1, 0xbc, 0xf7, 0x8a, 0x76, 0x6c, 0x69, 0x7e, 0xcf, 0xc5, 0xd8, 0x31, 0x2e, 0x05, 0xb3, + 0xf1, 0x19, 0xd5, 0xfc, 0x9d, 0x7f, 0x3f, 0x0f, 0x8d, 0x58, 0x8b, 0xd0, 0xf1, 0x9b, 0x9d, 0x4a, + 0xdc, 0x5a, 0x2c, 0xe6, 0x1b, 0xfd, 0x6b, 0x85, 0xec, 0xac, 0x8d, 0x53, 0x3e, 0x36, 0x4e, 0xca, + 0xf1, 0xb1, 0xa0, 0x3b, 0x3e, 0x3e, 0x80, 0x6a, 0x14, 0xb2, 0x2b, 0xde, 0x24, 0x56, 0x9f, 0xbc, + 0xef, 0x1a, 0x21, 0x45, 0xae, 0x92, 0x25, 0xdd, 0x55, 0xf2, 0xbb, 0x9a, 0x67, 0xdd, 0x02, 0x16, + 0x63, 0x64, 0x8d, 0xe8, 0x4f, 0xc5, 0xaf, 0xce, 0xf8, 0x02, 0x6a, 0x5a, 0xe3, 0x75, 0xef, 0xb4, + 0x5c, 0xcc, 0x3b, 0x4d, 0xdd, 0xaa, 0xcf, 0x47, 0xb7, 0xea, 0x8d, 0x5f, 0xcb, 0x43, 0x83, 0xed, + 0x2f, 0xc7, 0x3d, 0x3b, 0xf2, 0x26, 0xce, 0x08, 0xad, 0xc7, 0x6a, 0x87, 0x09, 0xee, 0x4f, 0xee, + 0x33, 0xb1, 0xc5, 0x38, 0xf3, 0xa7, 0x87, 0x82, 0xe1, 0x27, 0x87, 0x0a, 0x05, 0x63, 0x40, 0x83, + 0x51, 0x6b, 0xb4, 0x03, 0x47, 0xe1, 0xbd, 0xcc, 0xda, 0x29, 0xa5, 0xdb, 0x76, 0xc0, 0xc9, 0xf6, + 0xfb, 0xb0, 0xc2, 0x70, 0x30, 0xce, 0xc3, 0xd4, 0x99, 0x4c, 0x9c, 0xe8, 0xba, 0x68, 0xc1, 0x6c, + 0x9e, 0x52, 0x6a, 0xda, 0x21, 0x3d, 0x64, 0x09, 0x22, 0x1a, 0x58, 0x65, 0xec, 0x04, 0xf6, 0x49, + 0xe4, 0x9e, 0xaf, 0xbe, 0xa5, 0x7b, 0x45, 0xe4, 0xc1, 0x22, 0xbc, 0xaf, 0x44, 0x90, 0x13, 0xcc, + 0x9f, 0x58, 0x49, 0xe5, 0xe4, 0x4a, 0x32, 0xfe, 0x49, 0x1e, 0x6a, 0xda, 0xb2, 0x7c, 0x95, 0x23, + 0xff, 0x76, 0xca, 0xda, 0x5f, 0xd5, 0x0d, 0xfb, 0x6f, 0xc6, 0xab, 0x2c, 0xa8, 0x3b, 0x85, 0xfa, + 0x02, 0xbe, 0x05, 0x55, 0xb6, 0xeb, 0x3e, 0x44, 0xab, 0x88, 0x88, 0xd3, 0x87, 0x80, 0xa3, 0xf9, + 0x89, 0x4c, 0x7c, 0x88, 0x89, 0xa5, 0x28, 0xf1, 0x21, 0x4b, 0x7c, 0xd1, 0x9d, 0xa2, 0x4f, 0xa1, + 0x2e, 0x4a, 0xc5, 0x39, 0x15, 0xb2, 0xca, 0xaa, 0xc6, 0x4e, 0xa8, 0xf9, 0x36, 0x6b, 0xbc, 0x3a, + 0x3e, 0xf9, 0x22, 0xe3, 0x43, 0x99, 0xb1, 0xf2, 0xb2, 0x8c, 0x0f, 0xf9, 0x87, 0xb1, 0xa7, 0xae, + 0x69, 0xa1, 0x4f, 0xab, 0xa4, 0x63, 0x1f, 0xc0, 0x8a, 0x24, 0x57, 0x73, 0xd7, 0x76, 0x5d, 0x6f, + 0xee, 0x8e, 0xa8, 0xbc, 0xb2, 0x4e, 0x44, 0xd2, 0x71, 0x94, 0x62, 0x8c, 0x55, 0x00, 0x19, 0xee, + 0x1b, 0x7b, 0x1f, 0x4a, 0x5c, 0x58, 0xe0, 0x1c, 0x51, 0x36, 0xe1, 0xe2, 0x28, 0xe4, 0x1e, 0x94, + 0xb8, 0xcc, 0x90, 0xbf, 0x96, 0xd8, 0x70, 0x04, 0xa3, 0x0d, 0x84, 0x65, 0x3c, 0xa4, 0xa1, 0xef, + 0x8c, 0x82, 0xe8, 0x36, 0x7c, 0x29, 0xbc, 0x9a, 0x89, 0xba, 0x22, 0x63, 0x4a, 0x84, 0x89, 0x6a, + 0x23, 0x8e, 0xc3, 0x0e, 0xa6, 0x95, 0x58, 0x19, 0x82, 0x87, 0x9b, 0xc0, 0xfa, 0x09, 0x0d, 0x9f, + 0x53, 0xea, 0xba, 0x8c, 0x43, 0x1b, 0x51, 0x37, 0xf4, 0xed, 0x09, 0x9b, 0x24, 0xde, 0x83, 0x47, + 0xa9, 0x52, 0x23, 0xb5, 0xe4, 0x76, 0x94, 0x71, 0x47, 0xe5, 0xe3, 0xb4, 0x63, 0xed, 0x24, 0x2b, + 0x6d, 0xf3, 0x17, 0x60, 0xf3, 0xfa, 0x4c, 0x19, 0xba, 0x8b, 0x7b, 0x71, 0xaa, 0xa2, 0x4c, 0xf3, + 0x13, 0xcf, 0x0e, 0x79, 0x6b, 0x74, 0xca, 0xd2, 0x83, 0x9a, 0x96, 0x12, 0xf1, 0x17, 0x39, 0xe4, + 0x38, 0xf9, 0x07, 0x3b, 0x91, 0x5c, 0xcf, 0x9f, 0xa2, 0x29, 0x7c, 0x6c, 0x45, 0xa5, 0xe7, 0xcc, + 0xa5, 0x08, 0x8e, 0xde, 0x53, 0xc6, 0x16, 0x2c, 0xa1, 0xb8, 0xa1, 0x1d, 0x74, 0x2f, 0xe2, 0x50, + 0x8d, 0x55, 0x20, 0x3d, 0x4e, 0xbb, 0x74, 0x3f, 0xe1, 0x3f, 0x2c, 0x40, 0x4d, 0x03, 0xb3, 0xd3, + 0x08, 0x9d, 0xab, 0xad, 0xb1, 0x63, 0x4f, 0xa9, 0xf4, 0x3b, 0x68, 0x98, 0x0d, 0x84, 0xee, 0x0a, + 0x20, 0x3b, 0x8b, 0xed, 0x8b, 0x33, 0xcb, 0x9b, 0x87, 0xd6, 0x98, 0x9e, 0xf9, 0x54, 0xb6, 0xb2, + 0x6e, 0x5f, 0x9c, 0xf5, 0xe7, 0xe1, 0x2e, 0xc2, 0x64, 0xc4, 0x24, 0x0d, 0xab, 0xa0, 0x22, 0x26, + 0x45, 0x58, 0xc2, 0x29, 0x9d, 0xaf, 0xcc, 0xa2, 0x72, 0x4a, 0xe7, 0x22, 0x6c, 0xf2, 0x00, 0x2d, + 0xa5, 0x0f, 0xd0, 0x8f, 0x61, 0x9d, 0x1f, 0xa0, 0x82, 0x34, 0x5b, 0x89, 0x9d, 0xbc, 0x8a, 0xa9, + 0xa2, 0x93, 0x1a, 0x2f, 0xde, 0x64, 0x3d, 0x90, 0x64, 0x29, 0x70, 0x7e, 0xc4, 0x09, 0x59, 0xce, + 0x64, 0x3d, 0x13, 0x85, 0x0f, 0x9c, 0x1f, 0x51, 0x19, 0xb1, 0x29, 0x86, 0x29, 0x6e, 0x0c, 0x4e, + 0x1d, 0x37, 0x89, 0x69, 0x5f, 0xc6, 0x31, 0xab, 0x02, 0xd3, 0xbe, 0xd4, 0x31, 0x1f, 0xc1, 0xc6, + 0x94, 0x8e, 0x1d, 0x3b, 0x5e, 0xac, 0x15, 0x31, 0x87, 0xab, 0x3c, 0x59, 0xcb, 0x33, 0xe0, 0xda, + 0x04, 0x36, 0x1a, 0x3f, 0xf2, 0xa6, 0x27, 0x0e, 0xe7, 0x59, 0xb8, 0x5f, 0x60, 0xd1, 0x5c, 0x74, + 0xe7, 0xd3, 0x9f, 0x47, 0x30, 0xcb, 0x12, 0x18, 0x0d, 0xa8, 0x0d, 0x42, 0x6f, 0x26, 0xa7, 0x79, + 0x11, 0xea, 0xfc, 0x53, 0x44, 0x7b, 0xb8, 0x05, 0x37, 0x91, 0x24, 0x0c, 0xbd, 0x99, 0x37, 0xf1, + 0xce, 0xae, 0x62, 0xaa, 0xf5, 0x7f, 0x95, 0x83, 0x95, 0x58, 0xaa, 0x20, 0xaf, 0x1f, 0x73, 0x7a, + 0xa6, 0x6e, 0x8a, 0xe7, 0x62, 0xd7, 0x04, 0xd9, 0x7c, 0x71, 0x44, 0x4e, 0xcc, 0xe4, 0xed, 0xf1, + 0x76, 0x14, 0x0e, 0x4d, 0x66, 0xe4, 0x24, 0xa5, 0x95, 0x26, 0x29, 0x22, 0xbf, 0x0c, 0x94, 0x26, + 0x8b, 0xf8, 0x19, 0x71, 0xab, 0x73, 0x2c, 0xba, 0x5c, 0x88, 0xdf, 0xfb, 0xd2, 0xd5, 0xf0, 0xb2, + 0x05, 0x91, 0x6e, 0x3e, 0x30, 0x7e, 0x37, 0x0f, 0x10, 0xb5, 0x0e, 0x6f, 0x9e, 0x29, 0xbe, 0x25, + 0x87, 0x2e, 0xfe, 0x1a, 0x8f, 0xf2, 0x06, 0xd4, 0xd5, 0x6d, 0x90, 0x88, 0x13, 0xaa, 0x49, 0x18, + 0x63, 0x87, 0xde, 0x85, 0xa5, 0xb3, 0x89, 0x77, 0x82, 0x1c, 0xab, 0xe0, 0x5b, 0xd0, 0xb1, 0x07, + 0xcf, 0xa3, 0x45, 0x9e, 0xa4, 0x02, 0x1a, 0x2a, 0xde, 0xa9, 0x98, 0x79, 0x69, 0x24, 0xc6, 0x09, + 0x7d, 0x91, 0xe2, 0x84, 0xee, 0xa4, 0x06, 0xf7, 0xa7, 0xc3, 0x06, 0xfd, 0xb5, 0xbc, 0x72, 0x80, + 0x8f, 0xe6, 0xe5, 0xc5, 0x12, 0xf0, 0x8f, 0xe3, 0xae, 0xf7, 0x22, 0xff, 0x83, 0x2f, 0x60, 0xd1, + 0xe7, 0x47, 0xa4, 0x3c, 0x3f, 0x8b, 0x2f, 0x38, 0x3f, 0x1b, 0x7e, 0x8c, 0xef, 0xfa, 0x36, 0x34, + 0xed, 0xf1, 0x05, 0xf5, 0x43, 0x07, 0xcd, 0x79, 0xc8, 0xad, 0x0b, 0x77, 0x73, 0x0d, 0x8e, 0x6c, + 0xf1, 0x3b, 0xb0, 0x24, 0xe2, 0xa1, 0x28, 0x4c, 0x11, 0x28, 0x34, 0x02, 0x33, 0x44, 0xe3, 0x1f, + 0x49, 0x8f, 0xfb, 0xf8, 0x5a, 0x7b, 0xf1, 0xa8, 0xe8, 0x3d, 0xcc, 0xa7, 0x3d, 0x2c, 0xc4, 0xb2, + 0x16, 0x56, 0x42, 0x41, 0x1d, 0x39, 0x50, 0xd8, 0x08, 0xe3, 0xc3, 0x5a, 0x7c, 0x95, 0x61, 0x35, + 0xfe, 0x75, 0x0e, 0xca, 0xfb, 0xde, 0x6c, 0xdf, 0xe1, 0xf7, 0xb6, 0x70, 0xd3, 0x2a, 0x23, 0xf6, + 0x02, 0xfb, 0x44, 0xdf, 0xc2, 0x17, 0xdc, 0xe7, 0xce, 0x64, 0x3a, 0x1b, 0x71, 0xa6, 0xf3, 0xbb, + 0x70, 0x0b, 0x7d, 0x04, 0x7c, 0x6f, 0xe6, 0xf9, 0x8c, 0x70, 0xd8, 0x13, 0xce, 0x7c, 0x7a, 0x6e, + 0x78, 0x2e, 0x29, 0xf9, 0xcd, 0x53, 0x4a, 0x8f, 0x34, 0x8c, 0x43, 0x85, 0x80, 0xb1, 0x1c, 0x26, + 0xe1, 0x85, 0xc5, 0x95, 0x18, 0x82, 0x3b, 0xe6, 0xf4, 0x7d, 0x89, 0x25, 0x74, 0x10, 0x8e, 0xfc, + 0xb1, 0xf1, 0x19, 0x54, 0x95, 0x3e, 0x8c, 0xbc, 0x0b, 0xd5, 0x73, 0x6f, 0x26, 0x94, 0x66, 0xb9, + 0xd8, 0x9d, 0x77, 0xd1, 0x6b, 0xb3, 0x72, 0xce, 0x7f, 0x04, 0xc6, 0xff, 0x2b, 0x43, 0xb9, 0xeb, + 0x5e, 0x78, 0xce, 0x08, 0x7d, 0xf1, 0xa7, 0x74, 0xea, 0xc9, 0x10, 0x4f, 0xec, 0x37, 0x8a, 0xda, + 0x51, 0x2c, 0xcf, 0x82, 0x10, 0xb5, 0x55, 0x14, 0xcf, 0x35, 0x58, 0xf0, 0xf5, 0x60, 0x9c, 0x25, + 0x1f, 0x6f, 0x3a, 0xa9, 0xd3, 0xbb, 0xa4, 0x85, 0xea, 0x62, 0x65, 0x71, 0xf7, 0x67, 0x1c, 0x32, + 0x1e, 0x8f, 0xa1, 0x8a, 0x10, 0x1c, 0xb0, 0xd7, 0xa0, 0x2c, 0x54, 0xe3, 0xfc, 0xc2, 0x2b, 0x37, + 0x28, 0x08, 0x10, 0xae, 0x06, 0x9f, 0x72, 0x1f, 0x0f, 0xc5, 0x56, 0x17, 0xcc, 0xba, 0x04, 0xee, + 0xda, 0xdc, 0xc1, 0x9e, 0xe3, 0x73, 0x14, 0x7e, 0x0c, 0x01, 0x07, 0x21, 0x42, 0x46, 0xd8, 0xdb, + 0x6a, 0x66, 0xd8, 0x5b, 0xbc, 0x90, 0xa1, 0x68, 0x3e, 0xef, 0x22, 0xf0, 0x48, 0xa6, 0x1a, 0x5c, + 0x46, 0x99, 0x16, 0x6a, 0x27, 0x1e, 0xaa, 0x44, 0xaa, 0x9d, 0xde, 0x84, 0xc6, 0xa9, 0x3d, 0x99, + 0x9c, 0xd8, 0xa3, 0x67, 0x5c, 0xf9, 0x51, 0xe7, 0x0a, 0x62, 0x09, 0x44, 0xed, 0xc7, 0x1d, 0xa8, + 0x69, 0xb3, 0x8c, 0x7e, 0xe7, 0x45, 0x13, 0xa2, 0xf9, 0x4d, 0x2a, 0x41, 0x17, 0x5f, 0x41, 0x09, + 0xaa, 0xf9, 0xdf, 0x2f, 0xc5, 0xfd, 0xef, 0x6f, 0x21, 0x6d, 0x17, 0x0a, 0x90, 0x26, 0x0f, 0x9b, + 0x69, 0x8f, 0xb9, 0xfa, 0x03, 0x75, 0x7d, 0x7c, 0xf0, 0x78, 0xfa, 0xb2, 0xb8, 0xc0, 0x80, 0x30, + 0x8e, 0x72, 0x9b, 0x6b, 0xf2, 0x67, 0xb6, 0x33, 0xc6, 0xeb, 0x65, 0xc2, 0xe8, 0x63, 0x4f, 0xc3, + 0x23, 0xdb, 0x41, 0x7f, 0x4e, 0x99, 0x8c, 0x67, 0xf5, 0x0a, 0x1f, 0x7f, 0x91, 0x3c, 0xe0, 0x81, + 0x78, 0x14, 0xc6, 0x54, 0xc5, 0x1a, 0x31, 0x6b, 0x02, 0x05, 0xd7, 0xc1, 0x87, 0xe8, 0x06, 0x18, + 0x52, 0x8c, 0x26, 0xb2, 0xa8, 0x6c, 0x5e, 0x62, 0x95, 0xca, 0xff, 0xdc, 0x7a, 0xce, 0x31, 0x19, + 0xab, 0xc9, 0x8d, 0xf8, 0xeb, 0x31, 0x6e, 0x5c, 0xa0, 0xa2, 0x11, 0x9f, 0x23, 0x90, 0xcf, 0xb4, + 0x33, 0xa4, 0x85, 0xc8, 0xaf, 0x25, 0xca, 0xbf, 0xee, 0x42, 0xef, 0x6d, 0x00, 0x27, 0x60, 0x67, + 0x5e, 0x40, 0xdd, 0x31, 0x06, 0x05, 0xa9, 0x98, 0x55, 0x27, 0x78, 0xc2, 0x01, 0x29, 0x4d, 0xd7, + 0x66, 0x3a, 0x32, 0xef, 0x37, 0x7a, 0x04, 0xb5, 0xa1, 0xae, 0x8f, 0x04, 0xa9, 0x40, 0xb1, 0x7f, + 0xd4, 0xe9, 0x35, 0x6f, 0x90, 0x1a, 0x94, 0x07, 0x9d, 0xe1, 0xf0, 0x00, 0xbd, 0x05, 0xea, 0x50, + 0x51, 0x51, 0x01, 0xf2, 0xec, 0xab, 0xbd, 0xb3, 0xd3, 0x39, 0x1a, 0x76, 0x76, 0x9b, 0x85, 0xef, + 0x17, 0x2b, 0xf9, 0x66, 0xc1, 0xf8, 0x3f, 0x05, 0xa8, 0x69, 0x03, 0xf5, 0x62, 0x7a, 0x1d, 0x8f, + 0x3f, 0x95, 0x4f, 0xc6, 0x9f, 0xd2, 0x2d, 0x3d, 0x22, 0x46, 0x97, 0xb4, 0xf4, 0xbc, 0x09, 0x0d, + 0x11, 0xd4, 0x53, 0xf3, 0xf9, 0x28, 0x99, 0x75, 0x0e, 0x14, 0xd4, 0x1c, 0x63, 0x8c, 0x20, 0x12, + 0xde, 0xde, 0x2e, 0x89, 0xf5, 0x83, 0x20, 0xbc, 0xbf, 0x8d, 0x97, 0xef, 0x03, 0x6f, 0x72, 0x41, + 0x39, 0x06, 0x67, 0x61, 0x6b, 0x02, 0x36, 0x14, 0xf1, 0x5b, 0x04, 0xc9, 0xd4, 0x82, 0x5c, 0x94, + 0xcc, 0x3a, 0x07, 0x8a, 0x8a, 0xde, 0x97, 0x6b, 0x8c, 0x7b, 0xc0, 0x6d, 0xa4, 0x17, 0x4c, 0x6c, + 0x7d, 0x1d, 0xa4, 0x74, 0xab, 0x55, 0x5c, 0x3b, 0xdf, 0x4a, 0xe7, 0x7b, 0xb9, 0x8e, 0x95, 0xbc, + 0x0b, 0x64, 0x3a, 0x9b, 0x59, 0x19, 0x5a, 0xcf, 0xa2, 0xb9, 0x34, 0x9d, 0xcd, 0x86, 0x9a, 0xc2, + 0x8e, 0xbc, 0x06, 0x05, 0x7b, 0x3a, 0x43, 0xd2, 0x12, 0x69, 0x07, 0xdb, 0x87, 0x47, 0x26, 0x03, + 0x7f, 0x03, 0xea, 0xda, 0xdf, 0xcc, 0x41, 0xa1, 0x7d, 0x78, 0xf4, 0x67, 0xa4, 0x53, 0xc5, 0x80, + 0xa3, 0xd1, 0xf1, 0x80, 0xbf, 0xf9, 0x75, 0x48, 0x71, 0xa2, 0xf0, 0xcb, 0x02, 0xea, 0xdb, 0xf8, + 0xeb, 0x39, 0x20, 0x6d, 0x46, 0x91, 0x70, 0x40, 0x95, 0xa4, 0x1b, 0x9d, 0x33, 0x39, 0xfd, 0x9c, + 0xc9, 0x20, 0xe7, 0xf9, 0x4c, 0x72, 0xfe, 0x32, 0xc2, 0x17, 0xdb, 0xba, 0xcb, 0xa9, 0xad, 0x6b, + 0xec, 0x41, 0xed, 0x48, 0x0b, 0x16, 0x7d, 0x97, 0x9d, 0x8a, 0x32, 0x4c, 0x34, 0x3f, 0x2f, 0xb9, + 0x56, 0xd7, 0x17, 0xd1, 0xa1, 0xb5, 0x06, 0xe7, 0xb5, 0x06, 0x1b, 0x7f, 0x37, 0xc7, 0x43, 0x26, + 0xaa, 0xfe, 0x45, 0xf1, 0xa9, 0xa5, 0xc5, 0x36, 0x0a, 0xae, 0x53, 0x93, 0x36, 0x59, 0x11, 0x17, + 0x07, 0x5b, 0x6f, 0x79, 0xa7, 0xa7, 0x01, 0x95, 0x8e, 0x6f, 0x35, 0x84, 0xf5, 0x11, 0x24, 0xc5, + 0x1f, 0x26, 0x63, 0x39, 0xbc, 0xfc, 0x40, 0x78, 0xbb, 0x31, 0xf1, 0xe7, 0xd0, 0xbe, 0x14, 0xb5, + 0x06, 0x6c, 0x06, 0x84, 0xd9, 0x48, 0x06, 0x97, 0x50, 0xdf, 0xc6, 0xdf, 0x12, 0xf1, 0x7f, 0x92, + 0x53, 0x70, 0x1f, 0x2a, 0xaa, 0xd4, 0x38, 0x57, 0x21, 0x31, 0x55, 0x3a, 0xe3, 0x5d, 0x50, 0x1d, + 0x15, 0x6b, 0x31, 0xa7, 0x16, 0x68, 0xfa, 0xeb, 0x6a, 0xad, 0x7e, 0x0f, 0xc8, 0xa9, 0xe3, 0x27, + 0x91, 0x39, 0xf5, 0x68, 0x62, 0x8a, 0x86, 0x6d, 0x1c, 0xc3, 0x8a, 0x24, 0x7b, 0x9a, 0x4c, 0x16, + 0x9f, 0xdf, 0xdc, 0x4b, 0x0e, 0xb6, 0x7c, 0xea, 0x60, 0x33, 0x7e, 0xa3, 0x04, 0x65, 0x19, 0x9b, + 0x3d, 0x2b, 0x58, 0x78, 0x35, 0x1e, 0x2c, 0xbc, 0x15, 0x0b, 0x45, 0x8a, 0x53, 0x2f, 0x78, 0x9c, + 0x77, 0x92, 0x6c, 0x8a, 0x66, 0xc2, 0x8a, 0xb1, 0x2a, 0xc2, 0x84, 0x55, 0x8a, 0x9b, 0xb0, 0xb2, + 0x02, 0xa8, 0x73, 0x76, 0x3b, 0x15, 0x40, 0xfd, 0x16, 0x70, 0xde, 0x49, 0xf3, 0xf8, 0xad, 0x20, + 0x40, 0x04, 0x48, 0xd1, 0x58, 0xad, 0x4a, 0x92, 0xd5, 0x7a, 0x65, 0x36, 0xe8, 0x63, 0x58, 0xe0, + 0xb1, 0xc4, 0x44, 0xb0, 0x0c, 0x79, 0x58, 0x8a, 0xb1, 0x92, 0xff, 0xf9, 0x45, 0x32, 0x53, 0xe0, + 0xea, 0xf1, 0x76, 0x6b, 0xb1, 0x78, 0xbb, 0xba, 0x69, 0xad, 0x1e, 0x37, 0xad, 0xdd, 0x83, 0xa6, + 0x1a, 0x38, 0xd4, 0x09, 0xbb, 0x81, 0xb8, 0x17, 0xbf, 0x28, 0xe1, 0x8c, 0xbc, 0xf7, 0x82, 0xe8, + 0xb0, 0x5f, 0x8c, 0x1d, 0xf6, 0x8c, 0xf8, 0xb6, 0xc3, 0x90, 0x4e, 0x67, 0xa1, 0x3c, 0xec, 0xb5, + 0x98, 0xf5, 0x7c, 0xe6, 0xf9, 0x45, 0x3b, 0x39, 0xbd, 0x7c, 0x75, 0x6c, 0xc3, 0xe2, 0xa9, 0xed, + 0x4c, 0xe6, 0x3e, 0xb5, 0x7c, 0x6a, 0x07, 0x9e, 0x8b, 0xf4, 0x21, 0xe2, 0x3b, 0x44, 0x17, 0xf7, + 0x38, 0x8e, 0x89, 0x28, 0x66, 0xe3, 0x54, 0xff, 0xc4, 0x6b, 0xad, 0xfa, 0x48, 0xb0, 0x33, 0x58, + 0x84, 0xcc, 0xe0, 0x0e, 0x7c, 0xdd, 0x9e, 0xb5, 0x77, 0xd0, 0x7d, 0xbc, 0x3f, 0x6c, 0xe6, 0xd8, + 0xe7, 0xe0, 0x78, 0x67, 0xa7, 0xd3, 0xd9, 0xc5, 0x33, 0x19, 0x60, 0x61, 0xaf, 0xdd, 0x3d, 0x10, + 0x27, 0x72, 0xb1, 0x59, 0x32, 0xfe, 0x30, 0x0f, 0x35, 0xad, 0x37, 0x18, 0x0c, 0x87, 0xff, 0x64, + 0xf4, 0xb7, 0x2c, 0x82, 0xe1, 0x70, 0x48, 0x77, 0x4c, 0x1e, 0xa9, 0x39, 0xe2, 0x31, 0x7c, 0x6e, + 0xa7, 0x07, 0x64, 0x4b, 0x9e, 0x68, 0xda, 0x24, 0xa9, 0xe0, 0xf5, 0xf9, 0x6b, 0x83, 0xd7, 0x93, + 0xb7, 0x61, 0x49, 0xd6, 0x2c, 0xe7, 0x44, 0x58, 0x5f, 0x04, 0x58, 0x4c, 0xc9, 0xdb, 0x22, 0x9e, + 0x90, 0x38, 0x96, 0x19, 0x5e, 0x51, 0x3a, 0xba, 0xab, 0x93, 0x19, 0xa7, 0xae, 0x2c, 0x06, 0x4e, + 0xb8, 0x70, 0x28, 0x06, 0x47, 0x0c, 0xa7, 0x4c, 0x8e, 0x9d, 0x11, 0x0b, 0x89, 0x33, 0xe2, 0x13, + 0x80, 0xa8, 0x3f, 0xf1, 0xd1, 0xbd, 0x11, 0x1f, 0xdd, 0x9c, 0x36, 0xba, 0x79, 0xe3, 0x1f, 0x0a, + 0xca, 0x26, 0xa6, 0x4a, 0xe9, 0x62, 0xdf, 0x07, 0xa9, 0x1d, 0xb6, 0xf0, 0x62, 0xcc, 0x6c, 0x42, + 0x43, 0x79, 0xeb, 0x7f, 0x59, 0xa4, 0x74, 0x55, 0x42, 0x8a, 0x12, 0xe7, 0xd3, 0x94, 0xf8, 0x0d, + 0xa8, 0x63, 0x80, 0x4a, 0x51, 0x91, 0x8c, 0x10, 0x3d, 0xb5, 0x2f, 0x65, 0xdd, 0x31, 0x12, 0x5c, + 0x4c, 0x90, 0xe0, 0xbf, 0x9d, 0xe3, 0xd1, 0xcc, 0xa2, 0x86, 0x46, 0x34, 0x58, 0x95, 0x19, 0xa7, + 0xc1, 0x02, 0xd5, 0x54, 0xe9, 0xd7, 0xd0, 0xd5, 0x7c, 0x36, 0x5d, 0xcd, 0xa6, 0xd8, 0x85, 0x4c, + 0x8a, 0x6d, 0x5c, 0x42, 0x6b, 0x97, 0xb2, 0xa1, 0x68, 0x4f, 0x26, 0xc9, 0xb1, 0x7c, 0x00, 0xab, + 0x6c, 0x0a, 0xd1, 0x7f, 0x85, 0xa7, 0xe8, 0x27, 0x1a, 0xe1, 0x69, 0x32, 0x13, 0x1e, 0x6c, 0xf7, + 0x61, 0x59, 0xe4, 0xc0, 0x4d, 0xab, 0x87, 0x8e, 0x5b, 0xe2, 0x09, 0xe8, 0x77, 0xcb, 0x70, 0x8d, + 0x5b, 0x70, 0x33, 0xa3, 0x66, 0xa1, 0xb4, 0xfb, 0xcd, 0x1c, 0xac, 0xb5, 0x79, 0x88, 0xa4, 0x6f, + 0xec, 0xd2, 0xff, 0xe7, 0x70, 0x53, 0xdd, 0xa1, 0xd1, 0xee, 0xfe, 0xea, 0x8d, 0x94, 0xd7, 0x6f, + 0xb4, 0x9b, 0x63, 0xd8, 0xd6, 0x16, 0xac, 0x27, 0x5b, 0x23, 0x1a, 0xba, 0x07, 0xcb, 0xbb, 0xf4, + 0x64, 0x7e, 0x76, 0x40, 0x2f, 0xa2, 0x36, 0x12, 0x28, 0x06, 0xe7, 0xde, 0x73, 0x31, 0x50, 0xf8, + 0x1b, 0x9d, 0xec, 0x19, 0x8e, 0x15, 0xcc, 0xe8, 0x48, 0x1a, 0x7d, 0x10, 0x32, 0x98, 0xd1, 0x91, + 0xf1, 0x08, 0x88, 0x5e, 0x8e, 0x58, 0x23, 0x4c, 0x06, 0x9e, 0x9f, 0x58, 0xc1, 0x55, 0x10, 0xd2, + 0xa9, 0xbc, 0xff, 0x0e, 0xc1, 0xfc, 0x64, 0xc0, 0x21, 0xc6, 0x3b, 0x50, 0x3f, 0xb2, 0xaf, 0x4c, + 0xfa, 0x43, 0x71, 0x85, 0x7c, 0x03, 0xca, 0x33, 0xfb, 0x8a, 0x1d, 0x04, 0xca, 0xfe, 0x8b, 0xc9, + 0xc6, 0xef, 0x16, 0x61, 0x81, 0x63, 0x92, 0xbb, 0xfc, 0x5d, 0x1b, 0xc7, 0x45, 0x42, 0x2c, 0x8f, + 0x44, 0x0d, 0x94, 0x3a, 0x35, 0xf3, 0xe9, 0x53, 0x53, 0x28, 0xab, 0x65, 0xfc, 0x4d, 0x69, 0xa9, + 0x73, 0xe7, 0x53, 0x19, 0x74, 0x33, 0x1e, 0x10, 0xa8, 0x18, 0xbd, 0x94, 0xc4, 0x83, 0xa1, 0xc4, + 0x1d, 0x3c, 0x22, 0x49, 0x9b, 0xb7, 0x4e, 0x32, 0x03, 0xe2, 0xc0, 0xd4, 0x41, 0x99, 0xe2, 0x7c, + 0x59, 0xc6, 0x57, 0x88, 0x8b, 0xf3, 0x29, 0xb1, 0xbd, 0xf2, 0x72, 0xb1, 0x9d, 0x6b, 0xb1, 0x5f, + 0x20, 0xb6, 0xc3, 0x2b, 0x88, 0xed, 0xaf, 0xe0, 0x2b, 0x71, 0x13, 0x2a, 0xc8, 0xe1, 0x69, 0xe7, + 0x27, 0xe3, 0xec, 0xd8, 0xf9, 0xf9, 0xa9, 0x26, 0xd8, 0x72, 0xcf, 0x2e, 0xed, 0x00, 0x33, 0xe9, + 0x0f, 0x7f, 0x3a, 0x8a, 0xd1, 0xa7, 0x50, 0x16, 0x50, 0xb6, 0xa0, 0x5d, 0x7b, 0x2a, 0xa3, 0x4c, + 0xe3, 0x6f, 0x36, 0x6c, 0x18, 0x77, 0xf5, 0x87, 0x73, 0xc7, 0xa7, 0x63, 0x19, 0xfd, 0xd1, 0x41, + 0xea, 0xc1, 0x20, 0xac, 0x83, 0x4c, 0xc8, 0x76, 0xe5, 0x93, 0x16, 0x15, 0xb3, 0xec, 0x04, 0x4f, + 0xd8, 0xa7, 0x41, 0xa0, 0x89, 0x31, 0xfd, 0x67, 0x9e, 0x2f, 0xd9, 0x13, 0xe3, 0xf7, 0x72, 0xd0, + 0x14, 0xbb, 0x4b, 0xa5, 0xe9, 0x02, 0x6c, 0xe9, 0x3a, 0x47, 0xa4, 0x17, 0xc7, 0x72, 0x34, 0xa0, + 0x81, 0xaa, 0x3d, 0xc5, 0xab, 0x70, 0xd5, 0x64, 0x8d, 0x01, 0xf7, 0x04, 0xbf, 0xf2, 0x3a, 0xd4, + 0xe4, 0x15, 0xa0, 0xa9, 0x33, 0x91, 0x8f, 0xa2, 0xf1, 0x3b, 0x40, 0x87, 0xce, 0x44, 0xb2, 0x3a, + 0xbe, 0x2d, 0x62, 0x7e, 0xe4, 0x90, 0xd5, 0x31, 0xed, 0x90, 0x1a, 0x7f, 0x90, 0x83, 0x65, 0xad, + 0x2b, 0x62, 0xdf, 0x7e, 0x07, 0xea, 0xea, 0xa9, 0x11, 0xaa, 0x78, 0xec, 0x8d, 0x38, 0x8d, 0x8a, + 0xb2, 0xd5, 0x46, 0x0a, 0x12, 0xb0, 0xc6, 0x8c, 0xed, 0x2b, 0x7e, 0x4f, 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, 0x46, 0x10, 0xa4, 0xab, + 0x05, 0x0b, 0x5c, 0xab, 0xcf, 0x89, 0xd7, 0xfe, 0x0d, 0x53, 0x7c, 0x93, 0x8f, 0x5f, 0x51, 0xe9, + 0x2d, 0xc3, 0x85, 0x5c, 0x33, 0xfc, 0x85, 0xf4, 0xf0, 0x5f, 0x3f, 0xbc, 0x59, 0x4e, 0x05, 0xa5, + 0x2c, 0xa7, 0x82, 0x57, 0x31, 0xe5, 0xa7, 0x02, 0x56, 0x94, 0xd3, 0x81, 0xa3, 0x1f, 0xc1, 0x46, + 0x0c, 0x07, 0xa9, 0xb5, 0x73, 0xea, 0xa8, 0x17, 0x0f, 0x56, 0x35, 0xec, 0x81, 0x4c, 0xdb, 0x2e, + 0x43, 0x29, 0x18, 0x79, 0x33, 0x74, 0x8e, 0x8f, 0x8f, 0xaa, 0x38, 0x26, 0x7e, 0x3b, 0x07, 0xad, + 0xbd, 0x28, 0x02, 0xb7, 0x13, 0x84, 0x9e, 0xaf, 0x1e, 0x93, 0xb8, 0x0d, 0xc0, 0x1f, 0x68, 0x43, + 0x35, 0x88, 0x08, 0x9d, 0x86, 0x10, 0x54, 0x82, 0xdc, 0x84, 0x0a, 0x75, 0xc7, 0x3c, 0x91, 0xaf, + 0x86, 0x32, 0x75, 0xc7, 0x52, 0x85, 0x92, 0x3a, 0xe4, 0x1b, 0x71, 0xf6, 0x45, 0x04, 0x01, 0x62, + 0xa3, 0x43, 0x2f, 0x90, 0xd9, 0x28, 0xaa, 0x20, 0x40, 0x87, 0xf6, 0x25, 0xde, 0x71, 0x08, 0x8c, + 0x7f, 0x9c, 0x87, 0xa5, 0xa8, 0x7d, 0x3c, 0x0c, 0xda, 0xdd, 0x54, 0x40, 0x37, 0xe1, 0x0f, 0xa5, + 0x68, 0xf8, 0x5d, 0xb1, 0x24, 0x1c, 0x26, 0xad, 0x69, 0xaa, 0xf5, 0x0a, 0xdf, 0xa0, 0x5d, 0x97, + 0x18, 0x50, 0x93, 0x18, 0xde, 0x3c, 0xd4, 0x02, 0x5e, 0x57, 0x39, 0x4a, 0x7f, 0x1e, 0x32, 0xf1, + 0xda, 0x9e, 0x32, 0x6e, 0x45, 0x08, 0xb8, 0x25, 0x7b, 0x1a, 0x76, 0xf1, 0x25, 0x40, 0x06, 0x66, + 0xd9, 0xf8, 0x64, 0x32, 0x2c, 0x86, 0xdf, 0xe4, 0xd2, 0x16, 0x9f, 0x3d, 0x94, 0xb4, 0x74, 0x51, + 0x84, 0xbf, 0x3f, 0xa4, 0x44, 0x91, 0xd7, 0xa1, 0xc6, 0x0b, 0x8f, 0x62, 0x94, 0x60, 0xf4, 0xc9, + 0xb0, 0xeb, 0x62, 0xba, 0x50, 0x73, 0x7a, 0xf3, 0x98, 0xe6, 0x06, 0x78, 0x55, 0xf2, 0xd1, 0x36, + 0xd5, 0x63, 0x4b, 0x19, 0x21, 0x6b, 0x0a, 0xd6, 0x0b, 0x18, 0xb7, 0x72, 0x33, 0x63, 0x76, 0x05, + 0x31, 0xd8, 0x01, 0x2d, 0x5c, 0xbb, 0x9c, 0x04, 0x4e, 0x11, 0xd6, 0x25, 0xf5, 0x8d, 0x0f, 0xbd, + 0xd9, 0x3c, 0x8d, 0x03, 0x22, 0x29, 0x9c, 0x4f, 0x74, 0x2c, 0x98, 0x0e, 0xf2, 0x74, 0x7c, 0xb6, + 0xb9, 0x00, 0x7c, 0x04, 0x9b, 0x9d, 0x4b, 0x46, 0x58, 0x94, 0xb7, 0xff, 0xe8, 0xd9, 0x5c, 0xda, + 0x47, 0x13, 0x56, 0x96, 0xdc, 0x2b, 0x59, 0x59, 0xc6, 0x3c, 0x84, 0x85, 0x2a, 0xeb, 0xc7, 0x29, + 0x84, 0xeb, 0x97, 0x6c, 0xd7, 0x3a, 0xc1, 0x22, 0x64, 0xc4, 0x1c, 0x06, 0xe2, 0x85, 0x1a, 0x01, + 0x2c, 0x1d, 0xce, 0x27, 0xa1, 0xb3, 0xa3, 0x40, 0xe4, 0x63, 0x91, 0x07, 0xeb, 0x91, 0xa3, 0x96, + 0x59, 0x11, 0xa8, 0x8a, 0x70, 0xb0, 0xa6, 0xac, 0x20, 0x2b, 0x5d, 0xdf, 0xd2, 0x34, 0x5e, 0x83, + 0x71, 0x13, 0x36, 0xa2, 0x2f, 0x3e, 0x6c, 0xf2, 0x44, 0xfa, 0x3b, 0x39, 0x7e, 0xef, 0x8a, 0xa7, + 0x0d, 0x5c, 0x7b, 0x16, 0x9c, 0x7b, 0x21, 0xe9, 0xc0, 0x4a, 0xe0, 0xb8, 0x67, 0x13, 0xaa, 0x17, + 0x1f, 0x88, 0x41, 0x58, 0x8b, 0xb7, 0x8d, 0x67, 0x0d, 0xcc, 0x65, 0x9e, 0x23, 0x2a, 0x2d, 0x20, + 0xdb, 0xd7, 0x35, 0x32, 0x5a, 0x16, 0x89, 0xd1, 0x48, 0x37, 0xbe, 0x0b, 0x8b, 0xf1, 0x8a, 0xc8, + 0xa7, 0x22, 0xf2, 0x4b, 0xd4, 0xaa, 0x42, 0x22, 0xee, 0x45, 0xb4, 0x20, 0x6a, 0xd1, 0xd8, 0x07, + 0xc6, 0x5f, 0xcd, 0x41, 0xcb, 0xa4, 0x6c, 0xe5, 0x6a, 0xad, 0x94, 0x6b, 0xe6, 0x3b, 0xa9, 0x52, + 0xaf, 0xef, 0xab, 0x0c, 0x28, 0x23, 0x5b, 0xf4, 0xde, 0xb5, 0x93, 0xb1, 0x7f, 0x23, 0xd5, 0xa3, + 0xed, 0x0a, 0x2c, 0x70, 0x14, 0x63, 0x03, 0xd6, 0x44, 0x7b, 0x64, 0x5b, 0x22, 0x83, 0x7e, 0xac, + 0xc6, 0x98, 0x41, 0x7f, 0x13, 0x5a, 0x3c, 0x40, 0x83, 0xde, 0x09, 0x91, 0x71, 0x17, 0xc8, 0xa1, + 0x3d, 0xb2, 0x7d, 0xcf, 0x73, 0x8f, 0xa8, 0x2f, 0xfc, 0xf8, 0x91, 0x11, 0x45, 0x7b, 0xb7, 0xe4, + 0x98, 0xf9, 0x97, 0x7c, 0x09, 0xc0, 0x73, 0xa5, 0x87, 0x20, 0xff, 0x32, 0x7c, 0x58, 0xd9, 0xb6, + 0x9f, 0x51, 0x59, 0x92, 0x1c, 0xa2, 0x2f, 0xa0, 0x36, 0x53, 0x85, 0xca, 0x71, 0x97, 0x41, 0xb5, + 0xd2, 0xd5, 0x9a, 0x3a, 0x36, 0xa3, 0x52, 0xa8, 0xb0, 0xc5, 0x30, 0x35, 0x63, 0x79, 0xe6, 0x33, + 0xd0, 0x13, 0x7a, 0xd5, 0x1d, 0x1b, 0x0f, 0x61, 0x35, 0x5e, 0xa7, 0x20, 0x2d, 0x9b, 0x50, 0x99, + 0x0a, 0x98, 0x68, 0xbd, 0xfa, 0x66, 0x32, 0x0b, 0x93, 0x3b, 0x65, 0x9e, 0xee, 0xae, 0x8a, 0xb5, + 0xf0, 0x05, 0x6c, 0xa4, 0x52, 0x44, 0x81, 0x77, 0xa1, 0xae, 0x35, 0x84, 0x77, 0xa3, 0x68, 0x82, + 0x6a, 0x49, 0x60, 0x7c, 0x0e, 0x1b, 0x5c, 0x6c, 0x8b, 0xb2, 0xcb, 0x21, 0x48, 0xf4, 0x22, 0x97, + 0xec, 0xc5, 0xc7, 0x52, 0xd6, 0xd4, 0xb3, 0x46, 0x41, 0x2d, 0xc7, 0x98, 0x26, 0x9d, 0xbc, 0xe4, + 0xa7, 0x71, 0x0c, 0xeb, 0xe9, 0xe1, 0x63, 0xed, 0xff, 0x89, 0x86, 0x5c, 0x0e, 0x4f, 0x94, 0xac, + 0x86, 0xe7, 0xbf, 0xe6, 0xf8, 0xf8, 0xc4, 0x92, 0x44, 0x33, 0xc7, 0x40, 0xa6, 0x34, 0x3c, 0xf7, + 0xc6, 0x56, 0xba, 0xe6, 0x47, 0xca, 0xc7, 0x2c, 0x33, 0xef, 0xd6, 0x21, 0x66, 0xd4, 0x52, 0xc4, + 0x15, 0x8c, 0x69, 0x12, 0xbe, 0x39, 0x82, 0xf5, 0x6c, 0xe4, 0x0c, 0xcf, 0xac, 0x8f, 0xe2, 0xfc, + 0xfc, 0xed, 0x6b, 0xbb, 0xcf, 0x9a, 0xa5, 0xb3, 0xf7, 0xbf, 0x5b, 0x81, 0xb2, 0x50, 0xd5, 0x90, + 0x2d, 0x28, 0x8e, 0xa4, 0x97, 0x6f, 0x14, 0xd8, 0x54, 0xa4, 0xca, 0xff, 0x3b, 0xe8, 0xeb, 0xcb, + 0xf0, 0xc8, 0x17, 0xb0, 0x18, 0x77, 0x74, 0x49, 0x04, 0x20, 0x8a, 0x7b, 0xa8, 0x34, 0x46, 0x09, + 0x27, 0x82, 0x6a, 0xc4, 0x83, 0x71, 0xd6, 0xb4, 0x72, 0xae, 0x31, 0x69, 0x9e, 0xcb, 0xc4, 0xba, + 0xe0, 0xdc, 0xb6, 0x1e, 0x3e, 0xfa, 0x44, 0x18, 0x15, 0x6a, 0x08, 0x1c, 0x9c, 0xdb, 0x0f, 0x1f, + 0x7d, 0x92, 0x14, 0xd8, 0x44, 0xfc, 0x21, 0x4d, 0x60, 0x5b, 0x85, 0x12, 0x7f, 0x2e, 0x81, 0xbb, + 0x6b, 0xf2, 0x0f, 0xa9, 0xce, 0x98, 0xfb, 0xd4, 0x12, 0xb7, 0x7d, 0xf8, 0x29, 0xca, 0x9f, 0xb6, + 0x23, 0x22, 0x6d, 0x80, 0x49, 0x5c, 0x9d, 0xb8, 0x0e, 0x0b, 0xe7, 0xd1, 0xfb, 0x17, 0x0d, 0x53, + 0x7c, 0x19, 0xff, 0xab, 0x04, 0x35, 0x6d, 0x50, 0x48, 0x1d, 0x2a, 0x66, 0x67, 0xd0, 0x31, 0xbf, + 0xec, 0xec, 0x36, 0x6f, 0x90, 0x7b, 0xf0, 0x56, 0xb7, 0xb7, 0xd3, 0x37, 0xcd, 0xce, 0xce, 0xd0, + 0xea, 0x9b, 0x96, 0x8c, 0xb7, 0x7b, 0xd4, 0x7e, 0x7a, 0xd8, 0xe9, 0x0d, 0xad, 0xdd, 0xce, 0xb0, + 0xdd, 0x3d, 0x18, 0x34, 0x73, 0xe4, 0x35, 0x68, 0x45, 0x98, 0x32, 0xb9, 0x7d, 0xd8, 0x3f, 0xee, + 0x0d, 0x9b, 0x79, 0x72, 0x07, 0x6e, 0xed, 0x75, 0x7b, 0xed, 0x03, 0x2b, 0xc2, 0xd9, 0x39, 0x18, + 0x7e, 0x69, 0x75, 0x7e, 0xee, 0xa8, 0x6b, 0x3e, 0x6d, 0x16, 0xb2, 0x10, 0xf6, 0x87, 0x07, 0x3b, + 0xb2, 0x84, 0x22, 0xb9, 0x09, 0x6b, 0x1c, 0x81, 0x67, 0xb1, 0x86, 0xfd, 0xbe, 0x35, 0xe8, 0xf7, + 0x7b, 0xcd, 0x12, 0x59, 0x86, 0x46, 0xb7, 0xf7, 0x65, 0xfb, 0xa0, 0xbb, 0x6b, 0x99, 0x9d, 0xf6, + 0xc1, 0x61, 0x73, 0x81, 0xac, 0xc0, 0x52, 0x12, 0xaf, 0xcc, 0x8a, 0x90, 0x78, 0xfd, 0x5e, 0xb7, + 0xdf, 0xb3, 0xbe, 0xec, 0x98, 0x83, 0x6e, 0xbf, 0xd7, 0xac, 0x90, 0x75, 0x20, 0xf1, 0xa4, 0xfd, + 0xc3, 0xf6, 0x4e, 0xb3, 0x4a, 0xd6, 0x60, 0x39, 0x0e, 0x7f, 0xd2, 0x79, 0xda, 0x04, 0xd2, 0x82, + 0x55, 0xde, 0x30, 0x6b, 0xbb, 0x73, 0xd0, 0xff, 0xca, 0x3a, 0xec, 0xf6, 0xba, 0x87, 0xc7, 0x87, + 0xcd, 0x1a, 0x46, 0x3d, 0xef, 0x74, 0xac, 0x6e, 0x6f, 0x70, 0xbc, 0xb7, 0xd7, 0xdd, 0xe9, 0x76, + 0x7a, 0xc3, 0x66, 0x9d, 0xd7, 0x9c, 0xd5, 0xf1, 0x06, 0xcb, 0x20, 0x2e, 0xc4, 0x5a, 0xbb, 0xdd, + 0x41, 0x7b, 0xfb, 0xa0, 0xb3, 0xdb, 0x5c, 0x24, 0xb7, 0xe1, 0xe6, 0xb0, 0x73, 0x78, 0xd4, 0x37, + 0xdb, 0xe6, 0x53, 0x79, 0x61, 0xd6, 0xda, 0x6b, 0x77, 0x0f, 0x8e, 0xcd, 0x4e, 0x73, 0x89, 0xbc, + 0x01, 0xb7, 0xcd, 0xce, 0x0f, 0x8e, 0xbb, 0x66, 0x67, 0xd7, 0xea, 0xf5, 0x77, 0x3b, 0xd6, 0x5e, + 0xa7, 0x3d, 0x3c, 0x36, 0x3b, 0xd6, 0x61, 0x77, 0x30, 0xe8, 0xf6, 0x1e, 0x37, 0x9b, 0xe4, 0x2d, + 0xb8, 0xab, 0x50, 0x54, 0x01, 0x09, 0xac, 0x65, 0xd6, 0x3f, 0x39, 0xa5, 0xbd, 0xce, 0xcf, 0x0d, + 0xad, 0xa3, 0x4e, 0xc7, 0x6c, 0x12, 0xb2, 0x09, 0xeb, 0x51, 0xf5, 0xbc, 0x02, 0x51, 0xf7, 0x0a, + 0x4b, 0x3b, 0xea, 0x98, 0x87, 0xed, 0x1e, 0x9b, 0xe0, 0x58, 0xda, 0x2a, 0x6b, 0x76, 0x94, 0x96, + 0x6c, 0xf6, 0x1a, 0x21, 0xb0, 0xa8, 0xcd, 0xca, 0x5e, 0xdb, 0x6c, 0xae, 0x93, 0x25, 0xa8, 0x1d, + 0x1e, 0x1d, 0x59, 0xc3, 0xee, 0x61, 0xa7, 0x7f, 0x3c, 0x6c, 0x6e, 0xa4, 0x67, 0xe9, 0xa8, 0xfd, + 0xf4, 0xa0, 0xdf, 0xde, 0x6d, 0xb6, 0xc8, 0x1a, 0x34, 0xbb, 0xbd, 0x61, 0xc7, 0x64, 0xcb, 0x40, + 0x96, 0xfa, 0xdf, 0xca, 0x64, 0x15, 0x96, 0x64, 0x27, 0x24, 0xf4, 0x8f, 0xca, 0x64, 0x03, 0xc8, + 0x71, 0xcf, 0xec, 0xb4, 0x77, 0xd9, 0x98, 0xaa, 0x84, 0xff, 0x5e, 0x16, 0xe6, 0xe5, 0xdf, 0x2b, + 0x28, 0x3e, 0x30, 0x72, 0x30, 0x8b, 0xbf, 0x65, 0x55, 0xd7, 0xde, 0xa0, 0x7a, 0xd9, 0x7b, 0xa7, + 0x9a, 0x70, 0x5f, 0x48, 0x09, 0xf7, 0x29, 0xed, 0x51, 0x43, 0x97, 0x3c, 0xde, 0x84, 0xc6, 0x94, + 0xbf, 0x6b, 0x25, 0x1e, 0x46, 0x01, 0xe1, 0x6d, 0xc9, 0x81, 0xfc, 0x55, 0x94, 0xd4, 0x83, 0x9f, + 0xa5, 0xf4, 0x83, 0x9f, 0x59, 0x12, 0xe6, 0x42, 0x96, 0x84, 0x79, 0x1f, 0x96, 0x39, 0xd5, 0x72, + 0x5c, 0x67, 0x2a, 0xf5, 0x36, 0xe2, 0xf9, 0x4c, 0xa4, 0x5e, 0x1c, 0x2e, 0x05, 0x5a, 0x29, 0xf4, + 0x0a, 0xea, 0x52, 0x16, 0xf2, 0x6e, 0x4c, 0xd6, 0xe5, 0x44, 0x45, 0xc9, 0xba, 0xaa, 0x06, 0xfb, + 0x32, 0xaa, 0xa1, 0xa6, 0xd5, 0xc0, 0xe1, 0x58, 0xc3, 0x7d, 0x58, 0xa6, 0x97, 0xa1, 0x6f, 0x5b, + 0xde, 0xcc, 0xfe, 0xe1, 0x1c, 0x5d, 0x64, 0x6c, 0xd4, 0x22, 0xd5, 0xcd, 0x25, 0x4c, 0xe8, 0x23, + 0x7c, 0xd7, 0x0e, 0x6d, 0xe3, 0x17, 0x01, 0xd4, 0x81, 0x8b, 0xcf, 0x90, 0xba, 0x9e, 0xbc, 0xe8, + 0x5b, 0x37, 0xf9, 0x07, 0xce, 0x63, 0xe8, 0xf9, 0xf6, 0x19, 0xed, 0x4a, 0xab, 0x70, 0x04, 0x20, + 0xb7, 0xa0, 0xe0, 0xcd, 0xa4, 0x2f, 0x62, 0x55, 0x46, 0xfa, 0x9f, 0x99, 0x0c, 0x6a, 0x7c, 0x02, + 0xf9, 0xfe, 0xec, 0x5a, 0x2e, 0x0a, 0x5f, 0x5d, 0xe3, 0x4f, 0x2d, 0xe4, 0xd1, 0xff, 0x50, 0x7e, + 0xde, 0xff, 0x8b, 0x50, 0xd3, 0x1e, 0x69, 0x23, 0x1b, 0xb0, 0xf2, 0x55, 0x77, 0xd8, 0xeb, 0x0c, + 0x06, 0xd6, 0xd1, 0xf1, 0xf6, 0x93, 0xce, 0x53, 0x6b, 0xbf, 0x3d, 0xd8, 0x6f, 0xde, 0x60, 0x64, + 0xa6, 0xd7, 0x19, 0x0c, 0x3b, 0xbb, 0x31, 0x78, 0x8e, 0xbc, 0x0e, 0x9b, 0xc7, 0xbd, 0xe3, 0x41, + 0x67, 0xd7, 0xca, 0xca, 0x97, 0x67, 0xfb, 0x4a, 0xa4, 0x67, 0x64, 0x2f, 0xdc, 0xff, 0x25, 0x58, + 0x8c, 0x47, 0xbb, 0x21, 0x00, 0x0b, 0x07, 0x9d, 0xc7, 0xed, 0x9d, 0xa7, 0xfc, 0x25, 0x87, 0xc1, + 0xb0, 0x3d, 0xec, 0xee, 0x58, 0xe2, 0xe5, 0x06, 0x46, 0xc3, 0x72, 0xa4, 0x06, 0xe5, 0x76, 0x6f, + 0x67, 0xbf, 0x6f, 0x0e, 0x9a, 0x79, 0xf2, 0x1a, 0x6c, 0xc8, 0x2d, 0xb4, 0xd3, 0x3f, 0x3c, 0xec, + 0x0e, 0x91, 0x7c, 0x0f, 0x9f, 0x1e, 0xb1, 0x1d, 0x73, 0xdf, 0x86, 0x6a, 0xf4, 0xe8, 0x04, 0x92, + 0xc4, 0xee, 0xb0, 0xdb, 0x1e, 0x46, 0xe7, 0x41, 0xf3, 0x06, 0xa3, 0xb8, 0x11, 0x18, 0x5f, 0x8e, + 0x68, 0xe6, 0x78, 0x40, 0x00, 0x09, 0xe4, 0xb5, 0x37, 0xf3, 0x8c, 0x0c, 0x44, 0xd0, 0xed, 0xfe, + 0x90, 0x75, 0xe1, 0x97, 0x61, 0x31, 0xfe, 0xb6, 0x03, 0x69, 0x42, 0x9d, 0xd5, 0xaf, 0x55, 0x01, + 0xb0, 0xc0, 0x5b, 0xdc, 0xcc, 0x71, 0x9a, 0xbf, 0xd3, 0x3f, 0xec, 0xf6, 0x1e, 0xe3, 0x41, 0xd1, + 0xcc, 0x33, 0x50, 0xff, 0x78, 0xf8, 0xb8, 0xaf, 0x40, 0x05, 0x96, 0x83, 0x77, 0xa7, 0x59, 0xbc, + 0xff, 0x43, 0x58, 0x4e, 0xbd, 0x02, 0xc1, 0x5a, 0xdd, 0x3f, 0x1e, 0xee, 0xf4, 0x0f, 0xf5, 0x7a, + 0x6a, 0x50, 0xde, 0x39, 0x68, 0x77, 0x0f, 0xd1, 0x50, 0xd3, 0x80, 0xea, 0x71, 0x4f, 0x7e, 0xe6, + 0xe3, 0xef, 0x57, 0x14, 0x18, 0xf5, 0xda, 0xeb, 0x9a, 0x83, 0xa1, 0x35, 0x18, 0xb6, 0x1f, 0x77, + 0x9a, 0x45, 0x96, 0x57, 0x92, 0xb2, 0xd2, 0xfd, 0xcf, 0x61, 0x31, 0xee, 0x38, 0x1f, 0xb7, 0xbf, + 0x6d, 0xc2, 0xfa, 0x76, 0x67, 0xf8, 0x55, 0xa7, 0xd3, 0xc3, 0x29, 0xdf, 0xe9, 0xf4, 0x86, 0x66, + 0xfb, 0xa0, 0x3b, 0x7c, 0xda, 0xcc, 0xdd, 0xff, 0x02, 0x9a, 0x49, 0xa7, 0x8f, 0x98, 0x97, 0xcc, + 0x8b, 0xdc, 0x69, 0xee, 0xff, 0x87, 0x1c, 0xac, 0x66, 0x99, 0x07, 0xd9, 0xc2, 0x14, 0x84, 0x90, + 0x9d, 0x94, 0x83, 0x7e, 0xcf, 0xea, 0xf5, 0x31, 0x7e, 0xfb, 0x26, 0xac, 0x27, 0x12, 0x64, 0x2f, + 0x72, 0xe4, 0x16, 0x6c, 0xa4, 0x32, 0x59, 0x66, 0xff, 0x18, 0xe7, 0xb2, 0x05, 0xab, 0x89, 0xc4, + 0x8e, 0x69, 0xf6, 0xcd, 0x66, 0x81, 0xbc, 0x07, 0xf7, 0x12, 0x29, 0x69, 0xfe, 0x40, 0xb2, 0x0f, + 0x45, 0xf2, 0x0e, 0xbc, 0x99, 0xc2, 0x8e, 0x8e, 0x50, 0x6b, 0xbb, 0x7d, 0xc0, 0xba, 0xd7, 0x2c, + 0xdd, 0xff, 0x83, 0x22, 0x40, 0x74, 0x5d, 0x96, 0xd5, 0xbf, 0xdb, 0x1e, 0xb6, 0x0f, 0xfa, 0x6c, + 0xcf, 0x98, 0xfd, 0x21, 0x2b, 0xdd, 0xec, 0xfc, 0xa0, 0x79, 0x23, 0x33, 0xa5, 0x7f, 0xc4, 0x3a, + 0xb4, 0x01, 0x2b, 0x7c, 0xfd, 0x1d, 0xb0, 0x6e, 0xb0, 0xe5, 0xc2, 0x9f, 0x02, 0x60, 0x4c, 0xc8, + 0xf1, 0xd1, 0x9e, 0xd9, 0xef, 0x0d, 0xad, 0xc1, 0xfe, 0xf1, 0x70, 0x17, 0x5f, 0x16, 0xd8, 0x31, + 0xbb, 0x47, 0xbc, 0xcc, 0xe2, 0x8b, 0x10, 0x58, 0xd1, 0x25, 0xb6, 0xc1, 0x1f, 0xf7, 0x07, 0x83, + 0xee, 0x91, 0xf5, 0x83, 0xe3, 0x8e, 0xd9, 0xed, 0x0c, 0x30, 0xe3, 0x42, 0x06, 0x9c, 0xe1, 0x97, + 0xd9, 0x9a, 0x1d, 0x1e, 0x7c, 0x29, 0x0e, 0x3a, 0x86, 0x5a, 0x89, 0x83, 0x18, 0x56, 0x95, 0xcd, + 0x0e, 0x3b, 0x9c, 0x33, 0x4a, 0x86, 0x6b, 0xd2, 0x58, 0xbe, 0x1a, 0x3b, 0x4a, 0x53, 0x3b, 0x1f, + 0xb3, 0xd5, 0xb3, 0x93, 0x58, 0x2e, 0xe4, 0x48, 0x14, 0xff, 0xb6, 0xbb, 0x6b, 0x62, 0x86, 0xc5, + 0x14, 0x94, 0xe1, 0x2e, 0xb1, 0x45, 0xc8, 0x4e, 0x6f, 0x86, 0xd2, 0x94, 0x1f, 0x2c, 0x65, 0x99, + 0xf5, 0xf8, 0xab, 0xe3, 0xc3, 0xed, 0xbe, 0x64, 0x03, 0x78, 0x7b, 0x49, 0x06, 0x9c, 0xe1, 0xaf, + 0xe0, 0xd3, 0x0d, 0x9c, 0x1c, 0x21, 0xe2, 0xaa, 0x0e, 0x60, 0x18, 0x6b, 0x8c, 0x08, 0x4a, 0xc0, + 0xcf, 0x77, 0xcc, 0xbe, 0xc5, 0xf8, 0x2c, 0xe4, 0x11, 0x19, 0xfe, 0xfa, 0xf5, 0xc9, 0x2c, 0xf7, + 0xc6, 0xc3, 0x7f, 0xf1, 0x06, 0x54, 0xd5, 0x8d, 0x19, 0xf2, 0x7d, 0x68, 0xc4, 0xa2, 0x64, 0x90, + 0x5b, 0xd9, 0xb1, 0x33, 0x50, 0x8a, 0xda, 0x7c, 0xed, 0x45, 0x81, 0x35, 0xc8, 0xa1, 0xa6, 0xb8, + 0xe0, 0x85, 0xbd, 0x96, 0x54, 0x26, 0xc4, 0x4a, 0xbb, 0x7d, 0x4d, 0xaa, 0x28, 0xee, 0x09, 0xbe, + 0x92, 0x80, 0x51, 0x25, 0xc5, 0xf1, 0x42, 0x6e, 0x47, 0x21, 0xeb, 0x75, 0xb8, 0x2c, 0x50, 0x8a, + 0x89, 0x5a, 0xda, 0x2e, 0x0d, 0x6d, 0x67, 0x12, 0x90, 0x5d, 0xa8, 0x69, 0x0f, 0x0f, 0x93, 0x9b, + 0xd7, 0xbe, 0x92, 0xbc, 0xb9, 0x99, 0x95, 0x24, 0x9a, 0xf4, 0x5d, 0xa8, 0xaa, 0x87, 0x57, 0xc9, + 0x86, 0xf6, 0x30, 0xb0, 0xfe, 0x60, 0xed, 0x66, 0x2b, 0x9d, 0x20, 0xf2, 0xef, 0x42, 0x4d, 0x7b, + 0x25, 0x55, 0xb5, 0x22, 0xfd, 0x46, 0xab, 0x6a, 0x45, 0xd6, 0xa3, 0xaa, 0x07, 0xb0, 0x26, 0xd4, + 0x23, 0x27, 0xf4, 0xeb, 0x0c, 0x0f, 0x49, 0x0f, 0xcf, 0x83, 0x1c, 0xf9, 0x02, 0x2a, 0xf2, 0x6d, + 0x5e, 0xb2, 0x9e, 0xfd, 0xd6, 0xf1, 0xe6, 0x46, 0x0a, 0x2e, 0x9a, 0xd2, 0x06, 0x88, 0x5e, 0x59, + 0x25, 0xb2, 0xe3, 0xa9, 0xf7, 0x5c, 0xd5, 0xcc, 0x64, 0x3c, 0xc9, 0xba, 0x0b, 0x35, 0xed, 0x41, + 0x55, 0x35, 0x26, 0xe9, 0xc7, 0x58, 0xd5, 0x98, 0x64, 0xbd, 0xbf, 0xfa, 0x7d, 0x68, 0xc4, 0x5e, + 0x46, 0x55, 0xeb, 0x38, 0xeb, 0xdd, 0x55, 0xb5, 0x8e, 0xb3, 0x1f, 0x53, 0xdd, 0x85, 0x9a, 0xf6, + 0x5a, 0xa9, 0x6a, 0x51, 0xfa, 0xc9, 0x54, 0xd5, 0xa2, 0x8c, 0xc7, 0x4d, 0xd9, 0x6e, 0x88, 0x3f, + 0x55, 0xaa, 0x76, 0x43, 0xe6, 0x9b, 0xa7, 0x6a, 0x37, 0x64, 0xbf, 0x6f, 0xca, 0x96, 0x9e, 0x7a, + 0x1e, 0x85, 0x6c, 0xc4, 0xb4, 0x12, 0xd1, 0x3b, 0x2b, 0x6a, 0xe9, 0xa5, 0x5f, 0x52, 0x79, 0x0c, + 0x2b, 0x6a, 0xd1, 0xa8, 0xc7, 0x4d, 0x02, 0xd5, 0xa6, 0xcc, 0x27, 0x54, 0x36, 0x9b, 0xc9, 0xd4, + 0x07, 0x39, 0xf2, 0x19, 0x94, 0xc5, 0x8b, 0x11, 0x64, 0x2d, 0xf9, 0x82, 0x04, 0x6f, 0xc4, 0x7a, + 0xf6, 0xc3, 0x12, 0xe4, 0x08, 0x37, 0xb4, 0xfe, 0xa4, 0x83, 0xbe, 0x62, 0x33, 0x5e, 0x81, 0xd8, + 0x7c, 0xfd, 0xba, 0xe4, 0xa8, 0xc4, 0xe4, 0x33, 0x24, 0xb7, 0xaf, 0x8b, 0xf6, 0x15, 0x2f, 0xf1, + 0xba, 0xb0, 0xa4, 0x8f, 0xa1, 0xae, 0x3f, 0x53, 0x47, 0xf4, 0x7d, 0x98, 0x2c, 0xeb, 0x56, 0x66, + 0x9a, 0x28, 0xe8, 0x4b, 0x58, 0x57, 0xe3, 0xad, 0x87, 0x9e, 0x0a, 0xc8, 0x9d, 0x8c, 0x80, 0x54, + 0xb1, 0x51, 0xbf, 0x79, 0x6d, 0xc4, 0xaa, 0x07, 0x39, 0x24, 0xb2, 0xb1, 0x97, 0xa5, 0x22, 0x22, + 0x9b, 0xf5, 0xa0, 0x56, 0x44, 0x64, 0xb3, 0x9f, 0xa3, 0x6a, 0xc3, 0x92, 0x16, 0x3a, 0x6b, 0x70, + 0xe5, 0x8e, 0xd4, 0x7a, 0x4f, 0xc7, 0xd0, 0xdf, 0xcc, 0x52, 0xd2, 0x93, 0x1d, 0xa8, 0xe9, 0xd1, + 0xb7, 0x5e, 0x90, 0x7d, 0x43, 0x4b, 0xd2, 0x43, 0x9b, 0x3f, 0xc8, 0x91, 0x03, 0x68, 0x26, 0x63, + 0xe5, 0xaa, 0x2d, 0x9c, 0x15, 0x5f, 0x78, 0x33, 0x91, 0x18, 0x8b, 0xb0, 0xcb, 0xd6, 0x85, 0xa8, + 0x9a, 0x3f, 0x0a, 0xeb, 0xf9, 0xc9, 0xa3, 0x88, 0xc3, 0xe5, 0x30, 0xa8, 0xd2, 0x12, 0xa9, 0xd8, + 0xec, 0x7b, 0xb9, 0x07, 0x39, 0xb2, 0x07, 0xf5, 0x58, 0xa8, 0xc8, 0xd8, 0xe5, 0xad, 0x44, 0x37, + 0x5b, 0x7a, 0x5a, 0xa2, 0x9f, 0x87, 0xb0, 0x18, 0x77, 0x3a, 0x51, 0x0d, 0xcb, 0xf4, 0x8c, 0x51, + 0xd3, 0x97, 0xed, 0xa9, 0x42, 0x7e, 0x16, 0x6a, 0x8c, 0x26, 0x4b, 0xcf, 0x48, 0xa2, 0xd1, 0xe9, + 0xe4, 0x9c, 0x71, 0x98, 0xd0, 0x9a, 0x17, 0xfe, 0x72, 0x3e, 0x87, 0xfd, 0xfa, 0x0e, 0x7f, 0x06, + 0x5f, 0x3a, 0xc7, 0xb1, 0xf9, 0x7f, 0xd5, 0x42, 0xc8, 0x1e, 0xaf, 0x7c, 0xe8, 0xf1, 0x98, 0x0c, + 0x37, 0x35, 0x1c, 0x01, 0x7b, 0xb5, 0x36, 0xb4, 0x79, 0x1b, 0x44, 0x9e, 0xd8, 0x1a, 0x7c, 0xc5, + 0xb2, 0xc8, 0xa7, 0x00, 0x91, 0x53, 0x32, 0x49, 0xf8, 0xbd, 0xaa, 0x0d, 0x95, 0xe1, 0xb7, 0xdc, + 0xe1, 0xfb, 0x5d, 0x39, 0xde, 0xea, 0x47, 0x72, 0xdc, 0x07, 0x38, 0x76, 0x24, 0x27, 0x8b, 0xf9, + 0x08, 0x1a, 0x07, 0x9e, 0xf7, 0x6c, 0x3e, 0x53, 0x57, 0x75, 0xe2, 0x6e, 0x5f, 0xfb, 0x76, 0x70, + 0xbe, 0x99, 0x68, 0x16, 0x69, 0xc3, 0xb2, 0x22, 0x11, 0x91, 0xe7, 0x6f, 0x1c, 0x29, 0x46, 0x18, + 0x12, 0x05, 0x3c, 0xc8, 0x91, 0x87, 0x50, 0xdf, 0xa5, 0x23, 0x0c, 0x66, 0x83, 0x6e, 0x40, 0x2b, + 0x31, 0x97, 0x12, 0xee, 0x3f, 0xb4, 0xd9, 0x88, 0x01, 0x25, 0x89, 0x8b, 0x1c, 0xdd, 0xf4, 0x33, + 0x23, 0xee, 0x2d, 0x16, 0x23, 0x71, 0x29, 0x67, 0xb7, 0x2f, 0x61, 0x39, 0xe5, 0xec, 0xa5, 0xa8, + 0xdb, 0x75, 0x0e, 0x68, 0x9b, 0x77, 0xaf, 0x47, 0x10, 0xe5, 0x7e, 0x0f, 0x1a, 0x3c, 0xd2, 0xfd, + 0x09, 0xe5, 0xf7, 0xbe, 0x13, 0x71, 0x0c, 0xf5, 0x4b, 0xe5, 0x49, 0x92, 0xc4, 0x33, 0x3c, 0xc6, + 0x37, 0xb7, 0xb4, 0x5b, 0xd5, 0x6a, 0x5e, 0xd3, 0x37, 0xbd, 0xd5, 0xbc, 0x66, 0x5d, 0xe0, 0xfe, + 0x1c, 0x6a, 0x8f, 0x69, 0x28, 0xef, 0x29, 0x2b, 0xfe, 0x28, 0x71, 0x71, 0x79, 0x33, 0xe3, 0x76, + 0x39, 0xf9, 0x04, 0xb3, 0xaa, 0x98, 0x1b, 0xeb, 0x5a, 0x2d, 0x7a, 0xd6, 0xa5, 0x04, 0x9c, 0x71, + 0x1f, 0x5a, 0x38, 0x20, 0xd5, 0xf0, 0x74, 0xf8, 0x27, 0xd5, 0xf0, 0xac, 0xe8, 0x41, 0x3f, 0xcb, + 0x47, 0x40, 0xbb, 0x19, 0x1d, 0xb1, 0x60, 0xc9, 0x4b, 0xd4, 0xaa, 0xf9, 0x3a, 0xfa, 0x23, 0x80, + 0x41, 0xe8, 0xcd, 0x76, 0x6d, 0x3a, 0xf5, 0xdc, 0x88, 0x26, 0x44, 0x77, 0x72, 0xa3, 0x8d, 0xa8, + 0x5d, 0xcc, 0x25, 0x5f, 0x69, 0xbc, 0x69, 0x6c, 0x4a, 0xe4, 0xb4, 0x5f, 0x7b, 0x6d, 0x57, 0x75, + 0x27, 0xe3, 0xea, 0x2e, 0x12, 0x09, 0x88, 0x7c, 0xe9, 0x14, 0xa7, 0x99, 0x72, 0xd3, 0x53, 0x7b, + 0x3d, 0xc3, 0xf1, 0xee, 0xbb, 0x50, 0x8d, 0x9c, 0x90, 0x36, 0xa2, 0xd8, 0x64, 0x31, 0x97, 0x25, + 0x45, 0xbd, 0xd3, 0x0e, 0x40, 0x3d, 0x58, 0xe1, 0xcd, 0x51, 0xc7, 0x1f, 0xde, 0xd5, 0x54, 0x4f, + 0xc6, 0xa5, 0x3d, 0x6f, 0xd4, 0xfe, 0xc9, 0xf2, 0x1f, 0x61, 0xfb, 0x27, 0xe5, 0x60, 0xa0, 0xf6, + 0xcf, 0x75, 0x8e, 0x25, 0x6a, 0xff, 0x5c, 0xef, 0x9b, 0xd0, 0x83, 0x95, 0x0c, 0x57, 0x01, 0xf2, + 0x86, 0x14, 0x6c, 0xae, 0x75, 0x23, 0xd8, 0xcc, 0x34, 0x29, 0x93, 0x21, 0x6c, 0xf0, 0x3c, 0xed, + 0xc9, 0x24, 0x61, 0x99, 0x7e, 0x5d, 0xcb, 0x90, 0x61, 0x6d, 0x8f, 0xb1, 0x32, 0x09, 0x8b, 0x7b, + 0x0f, 0x9a, 0x49, 0xa3, 0x2e, 0xb9, 0x1e, 0x7d, 0xf3, 0x4e, 0x8c, 0x65, 0x4f, 0x1b, 0x82, 0xc9, + 0x97, 0xca, 0xb4, 0x9c, 0x68, 0xe3, 0x9d, 0xe8, 0xe9, 0xd3, 0x4c, 0x43, 0xb8, 0x92, 0x06, 0x32, + 0x2d, 0xd3, 0xe4, 0xe7, 0x60, 0x23, 0xb9, 0xa2, 0x65, 0xc9, 0x77, 0xb3, 0x86, 0xeb, 0x5a, 0x56, + 0x2e, 0xde, 0xa1, 0x07, 0x39, 0x46, 0x88, 0x75, 0x03, 0xb0, 0x5a, 0x48, 0x19, 0x96, 0x68, 0xb5, + 0x90, 0x32, 0x2d, 0xc6, 0x47, 0xb0, 0x94, 0xb0, 0xfd, 0x2a, 0x36, 0x38, 0xdb, 0x5a, 0xac, 0xd8, + 0xe0, 0xeb, 0x4c, 0xc6, 0x03, 0x68, 0x26, 0xad, 0xba, 0x6a, 0xae, 0xaf, 0xb1, 0x14, 0x6f, 0xde, + 0xb9, 0x36, 0x3d, 0xde, 0x4c, 0xcd, 0xfe, 0x19, 0x6b, 0x66, 0xda, 0x6a, 0x1b, 0x6b, 0x66, 0x86, + 0xf5, 0x75, 0xfb, 0x9d, 0x9f, 0xff, 0xd6, 0x99, 0x13, 0x9e, 0xcf, 0x4f, 0xb6, 0x46, 0xde, 0xf4, + 0x83, 0x89, 0xd4, 0x6a, 0x88, 0x40, 0x0a, 0x1f, 0x4c, 0xdc, 0xf1, 0x07, 0x58, 0xc0, 0xc9, 0xc2, + 0xcc, 0xf7, 0x42, 0xef, 0xa3, 0xff, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x5d, 0x18, 0x9c, 0x95, + 0x95, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto index 61fe65ec6de..7f5ff92e1a3 100644 --- a/lnrpc/rpc.proto +++ b/lnrpc/rpc.proto @@ -2493,12 +2493,22 @@ message Hop { /* An optional TLV record that signals the use of an MPP payment. If present, - the receiver will enforce that that the same mpp_record is included in the - final hop payload of all non-zero payments in the HTLC set. If empty, a - regular single-shot payment is or was attempted. + the receiver will enforce that the same mpp_record is included in the final + hop payload of all non-zero payments in the HTLC set. If empty, a regular + single-shot payment is or was attempted. */ MPPRecord mpp_record = 10; + /* + An optional TLV record that signals the use of an AMP payment. If present, + the receiver will treat all received payments including the same + (payment_addr, set_id) pair as being part of one logical payment. The + payment will be settled by XORing the root_share's together and deriving the + child hashes and preimages according to BOLT XX. Must be used in conjunction + with mpp_record. + */ + AMPRecord amp_record = 12; + /* An optional set of key-value TLV records. This is useful within the context of the SendToRoute call as it allows callers to specify arbitrary K-V pairs @@ -2525,6 +2535,14 @@ message MPPRecord { int64 total_amt_msat = 10; } +message AMPRecord { + bytes root_share = 1; + + bytes set_id = 2; + + uint32 child_index = 3; +} + /* A path through the channel graph which runs over one or more channels in succession. This struct carries all the information required to craft the diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json index 1c186ba052d..f19ac88c541 100644 --- a/lnrpc/rpc.swagger.json +++ b/lnrpc/rpc.swagger.json @@ -2536,6 +2536,23 @@ }, "description": "Details specific to AMP HTLCs." }, + "lnrpcAMPRecord": { + "type": "object", + "properties": { + "root_share": { + "type": "string", + "format": "byte" + }, + "set_id": { + "type": "string", + "format": "byte" + }, + "child_index": { + "type": "integer", + "format": "int64" + } + } + }, "lnrpcAbandonChannelResponse": { "type": "object" }, @@ -4025,7 +4042,11 @@ }, "mpp_record": { "$ref": "#/definitions/lnrpcMPPRecord", - "description": "An optional TLV record that signals the use of an MPP payment. If present,\nthe receiver will enforce that that the same mpp_record is included in the\nfinal hop payload of all non-zero payments in the HTLC set. If empty, a\nregular single-shot payment is or was attempted." + "description": "An optional TLV record that signals the use of an MPP payment. If present,\nthe receiver will enforce that the same mpp_record is included in the final\nhop payload of all non-zero payments in the HTLC set. If empty, a regular\nsingle-shot payment is or was attempted." + }, + "amp_record": { + "$ref": "#/definitions/lnrpcAMPRecord", + "description": "An optional TLV record that signals the use of an AMP payment. If present,\nthe receiver will treat all received payments including the same\n(payment_addr, set_id) pair as being part of one logical payment. The\npayment will be settled by XORing the root_share's together and deriving the\nchild hashes and preimages according to BOLT XX. Must be used in conjunction\nwith mpp_record." }, "custom_records": { "type": "object", From 352ce106587e57f15cd505d080ae56a9bfa6f925 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:53:13 -0700 Subject: [PATCH 20/22] lnrpc: add UnmarshalAMP decoding --- lnrpc/invoicesrpc/utils.go | 2 +- lnrpc/routerrpc/router_backend.go | 32 ++++++++ lnrpc/routerrpc/router_backend_test.go | 105 +++++++++++++++++++++++-- 3 files changed, 132 insertions(+), 7 deletions(-) diff --git a/lnrpc/invoicesrpc/utils.go b/lnrpc/invoicesrpc/utils.go index ad7c0e68cd4..9fdafcef847 100644 --- a/lnrpc/invoicesrpc/utils.go +++ b/lnrpc/invoicesrpc/utils.go @@ -129,7 +129,7 @@ func CreateRPCInvoice(invoice *channeldb.Invoice, rpcHtlc.Amp = &lnrpc.AMP{ RootShare: rootShare[:], SetId: setID[:], - ChildIndex: uint32(htlc.AMP.Record.ChildIndex()), + ChildIndex: htlc.AMP.Record.ChildIndex(), Hash: htlc.AMP.Hash[:], Preimage: preimage, } diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 7944dddcd0a..66fab66ef01 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -455,6 +455,11 @@ func UnmarshallHopWithPubkey(rpcHop *lnrpc.Hop, pubkey route.Vertex) (*route.Hop return nil, err } + amp, err := UnmarshalAMP(rpcHop.AmpRecord) + if err != nil { + return nil, err + } + return &route.Hop{ OutgoingTimeLock: rpcHop.Expiry, AmtToForward: lnwire.MilliSatoshi(rpcHop.AmtToForwardMsat), @@ -463,6 +468,7 @@ func UnmarshallHopWithPubkey(rpcHop *lnrpc.Hop, pubkey route.Vertex) (*route.Hop CustomRecords: customRecords, LegacyPayload: !rpcHop.TlvPayload, MPP: mpp, + AMP: amp, }, nil } @@ -895,6 +901,32 @@ func UnmarshalMPP(reqMPP *lnrpc.MPPRecord) (*record.MPP, error) { return record.NewMPP(total, addr), nil } +func UnmarshalAMP(reqAMP *lnrpc.AMPRecord) (*record.AMP, error) { + if reqAMP == nil { + return nil, nil + } + + reqRootShare := reqAMP.RootShare + reqSetID := reqAMP.SetId + + switch { + case len(reqRootShare) != 32: + return nil, errors.New("AMP root_share must be 32 bytes") + + case len(reqSetID) != 32: + return nil, errors.New("AMP set_id must be 32 bytes") + } + + var ( + rootShare [32]byte + setID [32]byte + ) + copy(rootShare[:], reqRootShare) + copy(setID[:], reqSetID) + + return record.NewAMP(rootShare, setID, reqAMP.ChildIndex), nil +} + // MarshalHTLCAttempt constructs an RPC HTLCAttempt from the db representation. func (r *RouterBackend) MarshalHTLCAttempt( htlc channeldb.HTLCAttempt) (*lnrpc.HTLCAttempt, error) { diff --git a/lnrpc/routerrpc/router_backend_test.go b/lnrpc/routerrpc/router_backend_test.go index f100909ad86..f92a6f15a2c 100644 --- a/lnrpc/routerrpc/router_backend_test.go +++ b/lnrpc/routerrpc/router_backend_test.go @@ -12,6 +12,7 @@ import ( "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/routing/route" + "github.com/stretchr/testify/require" "github.com/lightningnetwork/lnd/lnrpc" ) @@ -239,18 +240,18 @@ func (m *mockMissionControl) GetPairHistorySnapshot(fromNode, return routing.TimedPairResult{} } -type mppOutcome byte +type recordParseOutcome byte const ( - valid mppOutcome = iota + valid recordParseOutcome = iota invalid - nompp + norecord ) type unmarshalMPPTest struct { name string mpp *lnrpc.MPPRecord - outcome mppOutcome + outcome recordParseOutcome } // TestUnmarshalMPP checks both positive and negative cases of UnmarshalMPP to @@ -262,7 +263,7 @@ func TestUnmarshalMPP(t *testing.T) { { name: "nil record", mpp: nil, - outcome: nompp, + outcome: norecord, }, { name: "invalid total or addr", @@ -346,7 +347,7 @@ func testUnmarshalMPP(t *testing.T, test unmarshalMPPTest) { // Arguments that produce no MPP field should return no error and no MPP // record. - case nompp: + case norecord: if err != nil { t.Fatalf("failure for args resulting for no-mpp") } @@ -358,3 +359,95 @@ func testUnmarshalMPP(t *testing.T, test unmarshalMPPTest) { t.Fatalf("test case has non-standard outcome") } } + +type unmarshalAMPTest struct { + name string + amp *lnrpc.AMPRecord + outcome recordParseOutcome +} + +// TestUnmarshalAMP asserts the behavior of decoding an RPC AMPRecord. +func TestUnmarshalAMP(t *testing.T) { + rootShare := bytes.Repeat([]byte{0x01}, 32) + setID := bytes.Repeat([]byte{0x02}, 32) + + // All child indexes are valid. + childIndex := uint32(3) + + tests := []unmarshalAMPTest{ + { + name: "nil record", + amp: nil, + outcome: norecord, + }, + { + name: "invalid root share invalid set id", + amp: &lnrpc.AMPRecord{ + RootShare: []byte{0x01}, + SetId: []byte{0x02}, + ChildIndex: childIndex, + }, + outcome: invalid, + }, + { + name: "valid root share invalid set id", + amp: &lnrpc.AMPRecord{ + RootShare: rootShare, + SetId: []byte{0x02}, + ChildIndex: childIndex, + }, + outcome: invalid, + }, + { + name: "invalid root share valid set id", + amp: &lnrpc.AMPRecord{ + RootShare: []byte{0x01}, + SetId: setID, + ChildIndex: childIndex, + }, + outcome: invalid, + }, + { + name: "valid root share valid set id", + amp: &lnrpc.AMPRecord{ + RootShare: rootShare, + SetId: setID, + ChildIndex: childIndex, + }, + outcome: valid, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + testUnmarshalAMP(t, test) + }) + } +} + +func testUnmarshalAMP(t *testing.T, test unmarshalAMPTest) { + amp, err := UnmarshalAMP(test.amp) + switch test.outcome { + case valid: + require.NoError(t, err) + require.NotNil(t, amp) + + rootShare := amp.RootShare() + setID := amp.SetID() + require.Equal(t, test.amp.RootShare, rootShare[:]) + require.Equal(t, test.amp.SetId, setID[:]) + require.Equal(t, test.amp.ChildIndex, amp.ChildIndex()) + + case invalid: + require.Error(t, err) + require.Nil(t, amp) + + case norecord: + require.NoError(t, err) + require.Nil(t, amp) + + default: + t.Fatalf("test case has non-standard outcome") + } +} From 888af51ab4bec3f0718ca2d3e82e9afda990ba24 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:53:26 -0700 Subject: [PATCH 21/22] lntest: make buildRoute method on mppTestContext This will be reused by the amp itest. --- lntest/itest/lnd_mpp_test.go | 63 ++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/lntest/itest/lnd_mpp_test.go b/lntest/itest/lnd_mpp_test.go index 7ccca9e4fc6..0113a8fad97 100644 --- a/lntest/itest/lnd_mpp_test.go +++ b/lntest/itest/lnd_mpp_test.go @@ -74,36 +74,6 @@ func testSendToRouteMultiPath(net *lntest.NetworkHarness, t *harnessTest) { payAddr := decodeResp.PaymentAddr - // Helper function for Alice to build a route from pubkeys. - buildRoute := func(amt btcutil.Amount, hops []*lntest.HarnessNode) ( - *lnrpc.Route, error) { - - rpcHops := make([][]byte, 0, len(hops)) - for _, hop := range hops { - k := hop.PubKeyStr - pubkey, err := route.NewVertexFromStr(k) - if err != nil { - return nil, fmt.Errorf("error parsing %v: %v", - k, err) - } - rpcHops = append(rpcHops, pubkey[:]) - } - - req := &routerrpc.BuildRouteRequest{ - AmtMsat: int64(amt * 1000), - FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta, - HopPubkeys: rpcHops, - } - - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - routeResp, err := net.Alice.RouterClient.BuildRoute(ctxt, req) - if err != nil { - return nil, err - } - - return routeResp.Route, nil - } - // We'll send shards along three routes from Alice. sendRoutes := [][]*lntest.HarnessNode{ {ctx.carol, ctx.bob}, @@ -114,7 +84,7 @@ func testSendToRouteMultiPath(net *lntest.NetworkHarness, t *harnessTest) { responses := make(chan *lnrpc.HTLCAttempt, len(sendRoutes)) for _, hops := range sendRoutes { // Build a route for the specified hops. - r, err := buildRoute(shardAmt, hops) + r, err := ctx.buildRoute(ctxb, shardAmt, net.Alice, hops) if err != nil { t.Fatalf("unable to build route: %v", err) } @@ -394,3 +364,34 @@ func (c *mppTestContext) waitForChannels() { } } } + +// Helper function for Alice to build a route from pubkeys. +func (c *mppTestContext) buildRoute(ctxb context.Context, amt btcutil.Amount, + sender *lntest.HarnessNode, hops []*lntest.HarnessNode) (*lnrpc.Route, + error) { + + rpcHops := make([][]byte, 0, len(hops)) + for _, hop := range hops { + k := hop.PubKeyStr + pubkey, err := route.NewVertexFromStr(k) + if err != nil { + return nil, fmt.Errorf("error parsing %v: %v", + k, err) + } + rpcHops = append(rpcHops, pubkey[:]) + } + + req := &routerrpc.BuildRouteRequest{ + AmtMsat: int64(amt * 1000), + FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta, + HopPubkeys: rpcHops, + } + + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + routeResp, err := sender.RouterClient.BuildRoute(ctxt, req) + if err != nil { + return nil, err + } + + return routeResp.Route, nil +} From 730b718208ab0ee921f760c25024b71762b0037b Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Mar 2021 19:53:40 -0700 Subject: [PATCH 22/22] lntest: add AMP itest --- lnrpc/invoicesrpc/utils.go | 12 +- lntest/itest/lnd_amp_test.go | 208 ++++++++++++++++++++++++++ lntest/itest/lnd_test_list_on_test.go | 4 + 3 files changed, 220 insertions(+), 4 deletions(-) create mode 100644 lntest/itest/lnd_amp_test.go diff --git a/lnrpc/invoicesrpc/utils.go b/lnrpc/invoicesrpc/utils.go index 9fdafcef847..93300982dfd 100644 --- a/lnrpc/invoicesrpc/utils.go +++ b/lnrpc/invoicesrpc/utils.go @@ -2,7 +2,6 @@ package invoicesrpc import ( "encoding/hex" - "errors" "fmt" "github.com/btcsuite/btcd/btcec" @@ -24,7 +23,7 @@ func decodePayReq(invoice *channeldb.Invoice, if paymentRequest == "" { preimage := invoice.Terms.PaymentPreimage if preimage == nil { - return nil, errors.New("cannot reconstruct pay req") + return &zpay32.Invoice{}, nil } hash := [32]byte(preimage.Hash()) return &zpay32.Invoice{ @@ -51,6 +50,11 @@ func CreateRPCInvoice(invoice *channeldb.Invoice, return nil, err } + var rHash []byte + if decoded.PaymentHash != nil { + rHash = decoded.PaymentHash[:] + } + var descHash []byte if decoded.DescriptionHash != nil { descHash = decoded.DescriptionHash[:] @@ -144,8 +148,8 @@ func CreateRPCInvoice(invoice *channeldb.Invoice, } rpcInvoice := &lnrpc.Invoice{ - Memo: string(invoice.Memo[:]), - RHash: decoded.PaymentHash[:], + Memo: string(invoice.Memo), + RHash: rHash, Value: int64(satAmt), ValueMsat: int64(invoice.Terms.Value), CreationDate: invoice.CreationDate.Unix(), diff --git a/lntest/itest/lnd_amp_test.go b/lntest/itest/lnd_amp_test.go new file mode 100644 index 00000000000..d6c3b89a476 --- /dev/null +++ b/lntest/itest/lnd_amp_test.go @@ -0,0 +1,208 @@ +package itest + +import ( + "context" + "crypto/rand" + "time" + + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/amp" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/lntest" + "github.com/lightningnetwork/lnd/lntypes" + "github.com/stretchr/testify/require" +) + +func testSendToRouteAMP(net *lntest.NetworkHarness, t *harnessTest) { + ctxb := context.Background() + + ctx := newMppTestContext(t, net) + defer ctx.shutdownNodes() + + const ( + paymentAmt = btcutil.Amount(300000) + numShards = 3 + shardAmt = paymentAmt / numShards + chanAmt = shardAmt * 3 / 2 + ) + + // Set up a network with three different paths Alice <-> Bob. + // _ Eve _ + // / \ + // Alice -- Carol ---- Bob + // \ / + // \__ Dave ____/ + // + ctx.openChannel(ctx.carol, ctx.bob, chanAmt) + ctx.openChannel(ctx.dave, ctx.bob, chanAmt) + ctx.openChannel(ctx.alice, ctx.dave, chanAmt) + ctx.openChannel(ctx.eve, ctx.bob, chanAmt) + ctx.openChannel(ctx.carol, ctx.eve, chanAmt) + + // Since the channel Alice-> Carol will have to carry two + // shards, we make it larger. + ctx.openChannel(ctx.alice, ctx.carol, chanAmt+shardAmt) + + defer ctx.closeChannels() + + ctx.waitForChannels() + + // We'll send shards along three routes from Alice. + sendRoutes := [numShards][]*lntest.HarnessNode{ + {ctx.carol, ctx.bob}, + {ctx.dave, ctx.bob}, + {ctx.carol, ctx.eve, ctx.bob}, + } + + payAddr := make([]byte, 32) + _, err := rand.Read(payAddr) + require.NoError(t.t, err) + + setID := make([]byte, 32) + _, err = rand.Read(setID) + require.NoError(t.t, err) + + var sharer amp.Sharer + sharer, err = amp.NewSeedSharer() + require.NoError(t.t, err) + + childPreimages := make(map[lntypes.Preimage]uint32) + responses := make(chan *lnrpc.HTLCAttempt, len(sendRoutes)) + for i, hops := range sendRoutes { + // Build a route for the specified hops. + r, err := ctx.buildRoute(ctxb, shardAmt, net.Alice, hops) + if err != nil { + t.Fatalf("unable to build route: %v", err) + } + + // Set the MPP records to indicate this is a payment shard. + hop := r.Hops[len(r.Hops)-1] + hop.TlvPayload = true + hop.MppRecord = &lnrpc.MPPRecord{ + PaymentAddr: payAddr, + TotalAmtMsat: int64(paymentAmt * 1000), + } + + var child *amp.Child + if i < len(sendRoutes)-1 { + var left amp.Sharer + left, sharer, err = sharer.Split() + require.NoError(t.t, err) + + child = left.Child(uint32(i)) + } else { + child = sharer.Child(uint32(i)) + } + childPreimages[child.Preimage] = child.Index + + hop.AmpRecord = &lnrpc.AMPRecord{ + RootShare: child.Share[:], + SetId: setID, + ChildIndex: child.Index, + } + + // Send the shard. + sendReq := &routerrpc.SendToRouteRequest{ + PaymentHash: child.Hash[:], + Route: r, + } + + // We'll send all shards in their own goroutine, since SendToRoute will + // block as long as the payment is in flight. + go func() { + ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) + resp, err := net.Alice.RouterClient.SendToRouteV2(ctxt, sendReq) + if err != nil { + t.Fatalf("unable to send payment: %v", err) + } + + responses <- resp + }() + } + + // Assert that all of the child preimages are unique. + require.Equal(t.t, len(sendRoutes), len(childPreimages)) + + // Make a copy of the childPreimages map for validating the resulting + // invoice. + childPreimagesCopy := make(map[lntypes.Preimage]uint32) + for preimage, childIndex := range childPreimages { + childPreimagesCopy[preimage] = childIndex + } + + // Wait for all responses to be back, and check that they all + // succeeded. + for range sendRoutes { + var resp *lnrpc.HTLCAttempt + select { + case resp = <-responses: + case <-time.After(defaultTimeout): + t.Fatalf("response not received") + } + + if resp.Failure != nil { + t.Fatalf("received payment failure : %v", resp.Failure) + } + + preimage, err := lntypes.MakePreimage(resp.Preimage) + require.NoError(t.t, err) + + // Assert that the response includes one of our child preimages. + _, ok := childPreimages[preimage] + require.True(t.t, ok) + + // Remove this preimage from out set so that we ensure all + // responses have a unique child preimage. + delete(childPreimages, preimage) + } + childPreimages = childPreimagesCopy + + // 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) + require.Equal(t.t, payAddr, rpcInvoice.PaymentAddr) + + // Finally, assert that the proper set id is recorded for each htlc, and + // that the preimage hash pair is valid. + require.Equal(t.t, numShards, len(rpcInvoice.Htlcs)) + for _, htlc := range rpcInvoice.Htlcs { + require.NotNil(t.t, htlc.Amp) + 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) + + // Assert that the HTLC includes one of our child preimages. + childIndex, ok := childPreimages[childPreimage] + require.True(t.t, ok) + + // Assert that the correct child index is reflected. + require.Equal(t.t, childIndex, htlc.Amp.ChildIndex) + + // Remove this preimage from our set so that we ensure all HTLCs + // have a unique child preimage. + delete(childPreimages, childPreimage) + } +} diff --git a/lntest/itest/lnd_test_list_on_test.go b/lntest/itest/lnd_test_list_on_test.go index 216851e2509..7f630c0df7e 100644 --- a/lntest/itest/lnd_test_list_on_test.go +++ b/lntest/itest/lnd_test_list_on_test.go @@ -266,6 +266,10 @@ var allTestCases = []*testCase{ name: "sendtoroute multi path payment", test: testSendToRouteMultiPath, }, + { + name: "sendtoroute amp", + test: testSendToRouteAMP, + }, { name: "send multi path payment", test: testSendMultiPathPayment,